2017-02-03 10 views
0

Чтобы использовать диалоговые окна в приложениях с окнами, либо основной поток должен быть установлен как [STAThread], либо для запуска диалогового окна необходимо создать отдельный поток STA.STA поток для диалоговых окон

Вот и проблема, которую я не мог понять. Начальный поток STA не заканчивается «иногда», поэтому основной поток продолжает зависать на Join().

Теперь я преодолел с помощью Application.DoEvents() вместо t.Join(), и теперь кажется, что он работает нормально, но меня все равно интересует, что «иногда» в зависимости от. В примере я использую следующий статический метод, чтобы открыть в openfile-/SAVEFILE диалог:

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; 
     } 
    } 
} 

Так использование просто просто:

Dialog.clsShowDialog.STAShowDialog(new SaveFileDialog()); 
+0

В основном компоненты пользовательского интерфейса (COM) вообще не являются ThreaSafe и не будут работать должным образом в средах MTA. – codeteq

+0

Когда вы объявляете поток STA, вы обещаете, что вы не будете блокировать поток, и у вас будет насос сообщений. Если вы блокируете поток STA или у вас нет сообщения, то на него могут случиться случайные плохие вещи. См. [Этот ответ] (http://stackoverflow.com/a/4530773/80274) для получения более подробной информации. –

+1

@ScottChamberlain Правда, но 'Thread.Join' * - это перекачивание. Я подозреваю, что это будет нормально работать, если вызывающий абонент не был потоком пользовательского интерфейса. – Luaan

ответ

1

Я не мог понять, что именно делает вызывающий поток повешение(), когда он ждет завершения STA-потока, но похоже, что он иногда работает, иногда нет. Окончательное решение я решил преодолеть, используя:

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

вместо Join().

 Смежные вопросы

  • Нет связанных вопросов^_^