2015-12-21 48 views
1

我正在嘗試執行我的第一個多線程窗體表單應用程序,並且我有1個重要問題。 我知道我必須在我的線程中使用Invoke或BeginInvoke來更改我的表單中的RichTextBox,但是當我嘗試這樣做時,我的UI只是凍結,而控制檯正確打印我的結果。調用凍結我的Windows窗體

 class MyThread 
    { 
     public MyThread() 
     { 

     } 


     public void Run() 
     { 
      byte[] tmp; 
      while (true) 
      { 

       // lock (sem1) 
       Monitor.Enter(sem1); 
       { 
        if (end) 
        { 
         Monitor.Exit(sem1); 
         break; 
        } 
         tmp = inp.ReadNr(); 

        if (inp.End()) 
         end = true; 
       } 
       if(inOrder) 
       Monitor.Enter(sem2); 
       Monitor.Exit(sem1); 

       bool p = CSL.checkNr((byte[])tmp.Clone()); 
       Monitor.Enter(sem3); 
       if(inOrder) 
       Monitor.Exit(sem2); 
       { 
        outp.WriteNr(tmp, p); 
        //win.richTextBox2.AppendText(String.Join("", tmp) + '\n'); 
        win.richTextBox2.BeginInvoke(new Action(delegate() 
        { 
         win.richTextBox2.AppendText("wtf"); 
        })); 
       } 
       Monitor.Exit(sem3); 

      } 
     } 
    } 

「贏」 是我的Form1類的對象。我不能對付它......

編輯:

static public void loading() 
    { 
     outp = new oFile(); 
     Thread[] thr = new Thread[nrThreads]; 
     for (int a = 0; a < nrThreads; a++) 
      new Thread(new ThreadStart(new MyThread().Run)).Start(); 
     //new MyThread().Run(); 
     Console.ReadKey(); 
    } 

形式:

private void button1_Click(object sender, EventArgs e) 
    { 
     Program.loading(); 
    } 
+0

「Run」方法是在後臺線程還是UI線程上運行? – adv12

+3

作爲一個方面說明,直接使用'Monitor.Enter'和'Monitor.Exit'而不是'lock'語句是不尋常的,可能是一個壞主意,除非你真的知道你在做什麼。例如,如果你在'Enter'和'Exit'之間的代碼引發一個異常,那麼該對象將保持鎖定狀態。 – adv12

+0

@ adv12我剛剛編輯我的帖子如何運行我的線程。 UI線程正在運行創建和啓動我的線程的方法。 –

回答

3

這裏的問題是這一行Program.loading

Console.ReadKey(); 

這將停止在它的軌道中的主要GUI線程,讓我們看看現在會發生什麼:

  1. 消息張貼到主界面線程不會得到處理來自不同的線程(因爲你沒有返回回消息循環)
  2. 的BeginInvoke不會得到處理,因爲他們通過發佈信息工作到主GUI線程正在處理的同一個消息隊列(現在已經停止)
  3. 直到你按下一個鍵(假設這是可能的),一切都會停止。您會注意到,表單的繪製消息不會得到處理,最終表單將淡出並獲取「已停止響應」文本。

因此,刪除該行代碼,至少你的程序不應該像以前那樣停下來。


話雖如此,我敦促您嘗試更簡單的例子開始。您對多個顯示器進行交錯處理,手動處理讓我覺得您剛剛開始學習多線程編程,並開始使用一些需要非常準確地互鎖才能正確工作的複雜齒輪。

相反,我會請你看看async/await,在C#5中添加新的關鍵字來處理異步編程。雖然異步和多線程不是同一件事,但也不意味着另一個意思,異步編程通常可以讓您以大部分的方式實現響應式用戶界面,而這些用戶界面在等待事件時不會凍結。