2009-05-28 38 views
0

這些代碼生成此錯誤:如何運行多線程應用程序?

跨線程操作無效:控制'progressBar2'從其創建線程以外的線程訪問。

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace ThreadingTest1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     ThreadStart ts1; 
     ThreadStart ts2; 
     Thread t1; 
     Thread t2; 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      ts1 = new ThreadStart(z1); 
      ts2 = new ThreadStart(z2); 

      t1 = new Thread(ts1); 
      t2 = new Thread(ts2); 

      t1.Start(); 
      t2.Start(); 

      btnStart.Enabled = false; 
     } 

     public void z1() 
     { 

      for (int i = 1; i < 60; ++i) 
      { 
       progressBar1.Value += 1; 
       for (int j = 1; j < 10000000; ++j) 
       { 
        j += 1; 
       } 
      } 
     } 

     public void z2() 
     { 
      for (int k = 1; k < 100; ++k) 
      { 
       progressBar2.Value += 1; 
       for (int j = 1; j < 25000000; ++j) 
       { 
        j += 1; 
       } 
      } 
     } 

     private void btnstop_Click(object sender, EventArgs e) 
     { 
      t1.Suspend(); 
      t2.Suspend(); 
     } 

     private void btnContinue_Click(object sender, EventArgs e) 
     { 
      t1.Resume(); 
      t2.Resume(); 

     } 

     private void btnClose_Click(object sender, EventArgs e) 
     { 
      if (t1.IsAlive) 
      { 
       MessageBox.Show("Çalışan threadler var program sonlanamaz."); 
      } 
      else 
      { 
       this.Close(); 
      } 

     } 
    } 
}
+0

重複的一些信息,請參閱http://stackoverflow.com/questions/142003 – Rytmis 2009-05-28 11:16:00

回答

7

您不能在負責該控件的UI線程以外的線程中訪問UI控件。

請參閱我的線程教程中的WinForms頁面,並且還搜索BackgroundWorker上的教程,這是在.NET 2.0中引入的一個組件,它使生活變得更容易(特別是進度條)。

此外,我會盡量避免使用Thread.Suspend/Resume,寧願採取更合作的方法(例如Monitor.Wait/Pulse)。這可以讓你避免掛起線程同時持有鎖等

+0

喬恩,對於這種情況不會我的解決方案的工作? – 2009-05-28 11:21:34

1

對於這兩種Z1和Z2做到這一點: Z()InvokeRequired檢查後內添加zSafe() 呼叫zSafe()。

public void z1Safe() 
     { 

      for (int i = 1; i < 60; ++i) 
      { 
       progressBar1.Value += 1; 
       for (int j = 1; j < 10000000; ++j) 
       { 
        j += 1; 
       } 
      } 
     } 

     public void z1() 
     { 

      if (this.InvokeRequired) 
      { 
       this.Invoke((MethodInvoker)delegate { z1Safe(); }); 
      } 
      else 
       z1Safe(); 
     } 

我只是在我的windows窗體中爲asyn del call實現了一個類似的解決方案,它工作正常。

0

當您嘗試在多線程應用程序上工作時發生跨線程異常,這種情況很常見,當您嘗試在除自己線程之外的線程中調用控件的成員時會發生這種情況。爲了避免這種情況,您可以檢查該線程的InvokeRequired屬性在自己的線程中控制和調用委託,或使用BackgroundWorker在後臺運行進程(另一個線程)並處理其事件,當處理BackgroundWorker事件時,事件處理函數方法將在主線程上運行,因此不需要調用代表。

Here你可以找到關於BackgroundWorker的