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:
authorCarlos Alberto Cortez <calberto.cortez@gmail.com>2011-09-21 12:21:12 +0400
committerCarlos Alberto Cortez <calberto.cortez@gmail.com>2011-09-21 13:17:19 +0400
commit7d94e5306dd4da17d5f61edda5f739510f290c36 (patch)
treeda9a05c5824b0f5ef18724f22cfa02c30b8eec93 /main/src/addins/WindowsPlatform
parentc61889fec8b0bdf037c7ac99ad5dbd2ad3d63b74 (diff)
[Windows] Invoke the native dialogs in a separated thread.
Any access to the native Windows dialogs must be done from a thread with a single-threaded apartment model, and since marking the MD's main one has shown problems in the past, we proceed to access the native dialogs from a separated thread.
Diffstat (limited to 'main/src/addins/WindowsPlatform')
-rw-r--r--main/src/addins/WindowsPlatform/Dialogs/AddFileDialogHandler.cs12
-rw-r--r--main/src/addins/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs13
-rw-r--r--main/src/addins/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs45
3 files changed, 59 insertions, 11 deletions
diff --git a/main/src/addins/WindowsPlatform/Dialogs/AddFileDialogHandler.cs b/main/src/addins/WindowsPlatform/Dialogs/AddFileDialogHandler.cs
index 508d087bbf..fe5442a80f 100644
--- a/main/src/addins/WindowsPlatform/Dialogs/AddFileDialogHandler.cs
+++ b/main/src/addins/WindowsPlatform/Dialogs/AddFileDialogHandler.cs
@@ -14,9 +14,18 @@ namespace MonoDevelop.Platform
{
public bool Run (AddFileDialogData data)
{
+ var parentWindow = data.TransientFor ?? MessageService.RootWindow;
+
+ bool result = SelectFileDialogHandler.RunWinUIMethod (RunDialog, data);
+
+ parentWindow.Present ();
+ return result;
+ }
+
+ bool RunDialog (AddFileDialogData data)
+ {
Application.EnableVisualStyles ();
- var parentWindow = data.TransientFor ?? MessageService.RootWindow;
CustomAddFilesDialog adlg = new CustomAddFilesDialog();
adlg.StartLocation = AddonWindowLocation.Bottom;
adlg.BuildActions = data.BuildActions;
@@ -43,7 +52,6 @@ namespace MonoDevelop.Platform
adlg.Dispose();
}
- parentWindow.Present ();
return result;
}
}
diff --git a/main/src/addins/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs b/main/src/addins/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs
index 8fba6e6da1..ca9c4fc959 100644
--- a/main/src/addins/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs
+++ b/main/src/addins/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs
@@ -36,10 +36,19 @@ namespace MonoDevelop.Platform
public class OpenFileDialogHandler : IOpenFileDialogHandler
{
public bool Run (OpenFileDialogData data)
+ {
+ var parentWindow = data.TransientFor ?? MessageService.RootWindow;
+
+ bool result = SelectFileDialogHandler.RunWinUIMethod (RunDialog, data);
+
+ parentWindow.Present ();
+ return result;
+ }
+
+ bool RunDialog (OpenFileDialogData data)
{
Application.EnableVisualStyles ();
- var parentWindow = data.TransientFor ?? MessageService.RootWindow;
FileDialog fileDlg = null;
if (data.Action == Gtk.FileChooserAction.Open)
fileDlg = new OpenFileDialog ();
@@ -52,7 +61,6 @@ namespace MonoDevelop.Platform
using (dlg) {
if (dlg.ShowDialog () == DialogResult.Cancel) {
- parentWindow.Present ();
return false;
}
@@ -69,7 +77,6 @@ namespace MonoDevelop.Platform
data.CloseCurrentWorkspace = dlg.CloseCurrentWorkspace;
}
- parentWindow.Present ();
return true;
}
}
diff --git a/main/src/addins/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs b/main/src/addins/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs
index 7e8875f876..6a69b556b3 100644
--- a/main/src/addins/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs
+++ b/main/src/addins/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs
@@ -2,6 +2,7 @@
using System.IO;
using System.Collections.Generic;
using System.Text;
+using System.Threading;
using MonoDevelop.Components.Extensions;
using System.Windows.Forms;
using MonoDevelop.Core;
@@ -11,11 +12,20 @@ namespace MonoDevelop.Platform
{
class SelectFileDialogHandler : ISelectFileDialogHandler
{
- public bool Run(SelectFileDialogData data)
+ public bool Run (SelectFileDialogData data)
+ {
+ var parentWindow = data.TransientFor ?? MessageService.RootWindow;
+
+ bool result = RunWinUIMethod (RunDialog, data);
+
+ parentWindow.Present ();
+ return result;
+ }
+
+ bool RunDialog (SelectFileDialogData data)
{
Application.EnableVisualStyles ();
-
- var parentWindow = data.TransientFor ?? MessageService.RootWindow;
+
CommonDialog dlg = null;
if (data.Action == Gtk.FileChooserAction.Open)
dlg = new OpenFileDialog();
@@ -32,7 +42,6 @@ namespace MonoDevelop.Platform
using (dlg) {
WinFormsRoot root = new WinFormsRoot();
if (dlg.ShowDialog(root) == DialogResult.Cancel) {
- parentWindow.Present ();
return false;
}
@@ -46,11 +55,35 @@ namespace MonoDevelop.Platform
var folderDlg = dlg as FolderBrowserDialog;
data.SelectedFiles = new [] { new FilePath (folderDlg.SelectedPath) };
}
-
- parentWindow.Present ();
+
return true;
}
}
+
+ // Any native Winforms component needs to run on a thread marked as single-threaded apartment (STAThread).
+ // Marking the MD's Main method with STAThread has historically shown to be a source of several problems,
+ // thus we isolate the calls by creating a new thread for our calls.
+ // More info here: http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx
+ internal static bool RunWinUIMethod<T> (Func<T,bool> func, T data) where T : SelectFileDialogData
+ {
+ bool result = false;
+ var t = new Thread (() => {
+ try {
+ result = func (data);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Unhandled exception handling a native dialog", ex);
+ }
+ });
+ t.Name = "Win32 Interop Thread";
+ t.IsBackground = true;
+ t.SetApartmentState (ApartmentState.STA);
+
+ t.Start ();
+ while (!t.Join (50))
+ DispatchService.RunPendingEvents ();
+
+ return result;
+ }
internal static void SetCommonFormProperties (SelectFileDialogData data, FileDialog dialog)
{