Dot-Net
如何線上程中打開表單並強制它保持打開狀態
我仍然無法弄清楚如何在我在這裡討論的單獨的 UI 執行緒中創建 winforms 。
為了弄清楚這一點,我編寫了以下簡單的測試程序。我只是希望它在名為“UI 執行緒”的單獨執行緒上打開一個表單,並在表單打開時保持執行緒執行,同時允許使用者與表單互動(旋轉是作弊)。我理解為什麼下面會失敗並且執行緒會立即關閉,但我不確定我應該怎麼做才能修復它。
using System; using System.Windows.Forms; using System.Threading; namespace UIThreadMarshalling { static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); var tt = new ThreadTest(); ThreadStart ts = new ThreadStart(tt.StartUiThread); Thread t = new Thread(ts); t.Name = "UI Thread"; t.Start(); Thread.Sleep(new TimeSpan(0, 0, 10)); } } public class ThreadTest { Form _form; public ThreadTest() { } public void StartUiThread() { _form = new Form1(); _form.Show(); } } }
在一個新執行緒上,呼叫 Application.Run 傳遞表單對象,這將使執行緒在視窗打開時執行自己的消息循環。
然後,您可以在該執行緒上呼叫 .Join 以使您的主執行緒等到 UI 執行緒終止,或者使用類似的技巧來等待該執行緒完成。
例子:
public void StartUiThread() { using (Form1 _form = new Form1()) { Application.Run(_form); } }
我認為您的問題在於這個想法:“在名為’UI執行緒’的單獨執行緒上打開一個表單”
Windows 的工作方式是這樣的(請注意 Vista 可能會改變其中的一些現實):
有一個重要的執行緒稱為“主執行緒”或“ UI 執行緒”。該執行緒是處理Windows 消息的執行緒,例如“嘿,滑鼠點擊了這個像素”。
這些消息進入隊列,主執行緒在不忙於做其他事情時處理它們。
因此,如果你在主執行緒上呼叫 foo() 函式,如果需要很長時間,則在此期間不會處理任何 windows 消息,因此不會發生使用者互動。
主執行緒還在螢幕上繪製 UI,因此長時間執行的 foo() 也會阻止您的應用繪製。
除了這個神聖而特殊的主執行緒之外的所有其他執行緒都是 grunt 工作執行緒。這些工作執行緒可以做事,但它們永遠不能直接與使用者界面互動。
這種現實導致了兩個問題:
- 擺脫主執行緒:由於您不希望長時間執行的 foo() 停止所有使用者互動,因此您需要將該工作傳遞給工作執行緒。
- 回到主執行緒:當長時間執行的 foo() 完成時,您可能希望通過在 UI 中執行某些操作來通知使用者,但您不能在工作執行緒中執行此操作,因此您需要“返回”到主執行緒。
因此,我相信您在上述程序中的問題非常普遍:您的目標是不正確的,因為除了神聖的主執行緒之外,不應在任何執行緒中呼叫 _form.Show() 。