Um Dialogfelder in Windows-Formularanwendungen zu verwenden, sollte entweder der Hauptthread auf [STAThread]
festgelegt werden oder ein separater STA-Thread muss erstellt werden, damit das Dialogfeld ausgeführt werden kann.STA-Thread für Dialogfelder
Hier kommt das Problem, das ich nicht wirklich verstehen konnte. Ein gestarteter STA-Thread wird nicht "manchmal" beendet, sodass der Hauptthread weiterhin auf Join() auflegt.
Jetzt überwinde ich mit Application.DoEvents()
anstelle der t.Join()
und jetzt scheint es funktioniert gut, aber ich würde immer noch interessiert sein, was "manchmal" ist abhängig von. Im Beispiel verwende ich die folgende statische Methode einen openfile-/Savefile Dialog zu öffnen:
using System.Windows.Forms;
namespace Dialog
{
public class clsDialogState
{
public DialogResult result;
public FileDialog dialog;
public void ThreadProcShowDialog()
{
result = DialogResult.None;
result = dialog.ShowDialog();
}
}
public static class clsShowDialog
{
public static DialogResult STAShowDialog(FileDialog dialog)
{
clsDialogState state = new clsDialogState();
state.dialog = dialog;
System.Threading.Thread t = new System.Threading.Thread(state.ThreadProcShowDialog);
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
//t.Join(); //Main thread might hang up here
while (state.result == DialogResult.None) Application.DoEvents(); //Everything is refreshed/repainted fine
return state.result;
}
}
}
So ist die Nutzung einfach nur:
Dialog.clsShowDialog.STAShowDialog(new SaveFileDialog());
Meistens sind UI-Komponenten (COM) nicht ThreaSafe und werden in MTA-Umgebungen nicht ordnungsgemäß ausgeführt. – codeteq
Wenn Sie eine Thread-STA deklarieren, geben Sie eine Zusage, dass Sie den Thread nicht blockieren und eine Nachrichtenpumpe ausgeführt wird. Wenn du einen STA-Thread blockierst oder keine Nachricht darauf pumpst, können wahllos schlechte Dinge passieren. Weitere Informationen finden Sie [diese Antwort] (http://stackoverflow.com/a/4530773/80274). –
@ScottChamberlain True, aber 'Thread.Join' * ist * ein Pumpwarte. Ich vermute, das würde gut funktionieren, wenn der Aufrufer kein UI-Thread wäre. – Luaan