Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVsevolod Kukol <sevoku@microsoft.com>2017-03-20 11:39:34 +0300
committerVsevolod Kukol <sevoku@microsoft.com>2017-03-20 11:39:34 +0300
commit8d9a8e0a5e932aaaf829b287b364379a97b29f32 (patch)
treea20f87a6e4caee01824e9304f5a87c8ee90b762b /main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook
parent2d059533ec9f5e85394d2cbf70fcf5e19291c1d4 (diff)
[Ide] Fix IWorkbenchWindow.Closing event handling with async operations
If a workbench window contains an unsaved document, we ask the user to save it and run the save operation asynchronously. This is controlled by the WorkbenchWindowEventArgs.Cancel property and the result contols whether we set specific Gtk/GLib events as hanled or not (i.e. in order to allow or disallow Gtk to close a window). The first problem here was the async EventHandler for the Closing event which was not awaited and the window was closed before the Save operation had a chance to run to completion. This is solved by an EventHandler delegate returning a Task, making it possible to await the handlers subscribed to the event. The second problem with this approach was that Gtk doesn't know anything about awaiting Tasks and if one of its event handlers leaves the synchronization context (like the asynchrounous file saving), it will let the signal pass without waiting for its handled state to be updated. This is solved by delaying window closing/destruction (always set the initial delete/close event handled state and close the window in a continuation task synchronized with the UI thread) (fix bug #53089)
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs13
1 files changed, 11 insertions, 2 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs
index a421e25963..6acbdebd57 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockWindow.cs
@@ -92,8 +92,17 @@ namespace MonoDevelop.Components.DockNotebook
foreach (var d in documents) {
if (howManyDirtyFiles > 1)
d.Window.CloseWindow (true);
- else if (!d.Close ())
- return true;
+ else {
+ // d.Close() could leave the UI synchronization context, letting the Gtk signal handler pass
+ // and Gtk would destroy the window immediately. Since we need to preserve the window
+ // state until the async document.Close () has finished, we interrupt the signal (return true)
+ // and destoy the window in a continuation task after the document has been closed.
+ d.Close ().ContinueWith ((arg) => {
+ if (arg.Result)
+ Destroy ();
+ }, Core.Runtime.MainTaskScheduler);
+ return true;
+ }
}
return base.OnDeleteEvent (evnt);
}