2013-03-22 22 views
1

我是C#的初学者。当我使用win.forms时,线程出现问题。我的应用程序冻结。这个代码有什么问题?我正在使用msdn的微软示例。 这里是我的代码:C#中的多线程与Win.Forms控件

delegate void SetTextCallback(object text); 

    private void WriteString(object text) 
    { 
     // InvokeRequired required compares the thread ID of the 
     // calling thread to the thread ID of the creating thread. 
     // If these threads are different, it returns true. 
     if (this.textBox1.InvokeRequired) 
     { 
      SetTextCallback d = new SetTextCallback(WriteString); 
      this.Invoke(d, new object[] { text }); 
     } 
     else 
     { 
      for (int i = 0; i <= 1000; i++) 
      { 
       this.textBox1.Text = text.ToString(); 
      } 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 

     Thread th_1 = new Thread(WriteString); 
     Thread th_2 = new Thread(WriteString); 
     Thread th_3 = new Thread(WriteString); 
     Thread th_4 = new Thread(WriteString); 

     th_1.Priority = ThreadPriority.Highest; // самый высокий 
     th_2.Priority = ThreadPriority.BelowNormal; // выше среднего 
     th_3.Priority = ThreadPriority.Normal; // средний 
     th_4.Priority = ThreadPriority.Lowest; // низкий 

     th_1.Start("1"); 
     th_2.Start("2"); 
     th_3.Start("3"); 
     th_4.Start("4"); 

     th_1.Join(); 
     th_2.Join(); 
     th_3.Join(); 
     th_4.Join(); 
    } 
+0

也不例外,我的表单刚刚冻结 – 2013-03-22 19:42:33

+0

您是否尝试调试应用程序以查看它正在被挂起的位置? – 2013-03-22 19:42:53

+0

嗯,很高兴知道!它什么时候冻结? – 2013-03-22 19:42:55

回答

4

有一个僵局 - UI线程在等待线程与Thread.Join()完成而工作线程试图使用阻塞Control.Invoke()发送消息给UI。在通过的BeginInvoke(线程代码)更换调用会使僵局消失

if (this.textBox1.InvokeRequired) 
    { 
     SetTextCallback d = new SetTextCallback(WriteString); 
     // BeginInvoke posts message to UI thread asyncronously 
     this.BeginInvoke(d, new object[] { text }); 
    } 
    else 
    { 
     this.textBox1.Text = text.ToString(); 
    } 
+0

它的工作,但不是我的预期,它工作正常,当我添加System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;在MyApp_Load中为 。但我读过,不推荐。 – 2013-03-22 19:50:23

+0

尝试添加System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false并在WriteString中删除全部并添加textBox1.Text = text.ToString();这是我期望的结果,但我读到它不推荐设置CheckForIllegalCrossThreadCalls = false – 2013-03-22 19:55:03

+0

你在期待什么? – alexm 2013-03-22 19:55:59

0

冻结,因为加入的呼叫。 Thread.Join()使当前线程在另一个完成后等待。

+0

为什么它不冻结,如果我添加System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;在MyApp_Load中? – 2013-03-22 19:51:59

+0

@goodspeed - 当您禁用检查时,您会消除死锁,因为InvokeRequired始终返回false。 – alexm 2013-03-22 19:59:59

+0

正是什么alexm说。您可以删除所有.Join()调用,因为代码中没有任何逻辑需要在所有线程执行其他操作之后等待。 – 2013-03-22 20:02:57