2017-02-03 3 views
0

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()); 
+0

Meistens sind UI-Komponenten (COM) nicht ThreaSafe und werden in MTA-Umgebungen nicht ordnungsgemäß ausgeführt. – codeteq

+0

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). –

+1

@ScottChamberlain True, aber 'Thread.Join' * ist * ein Pumpwarte. Ich vermute, das würde gut funktionieren, wenn der Aufrufer kein UI-Thread wäre. – Luaan

Antwort

1

ich nicht genau herausfinden konnte, was die aufrufenden Thread hängen macht up auf der join(), wenn es darauf wartet, dass ein STA-Thread beendet wird, aber es sieht so aus, als ob es manchmal funktioniert, manchmal nicht. Schließlich entschied ich mich zu überwinden mit:

while (InvokeResult == DialogResult.None) Application.DoEvents(); 

anstelle der Join().

Verwandte Themen