2010-11-14 56 views
1
private void button1_Click(object sender, EventArgs e) 
    { 
     PROGRESS_BAR.Minimum = 0; 
     PROGRESS_BAR.Maximum = 100; 
     PROGRESS_BAR.Value = 0; 

     for (int i = 0; i < 100; i++) 
     { 
      Thread t = new Thread(new ThreadStart(updateProgressBar)); 
      t.IsBackground = true; 
      t.Start(); 
     } 

    } 

    private void updateProgressBar() 
    { 
      PROGRESS_BAR.PerformStep(); 
      Thread.Sleep(4000); 
    } 

我总是得到这个错误: 跨线程操作无效:控制“”从比它创建的线程以外的线程访问。无法更新螺纹加工进度条在C#

我试图在谷歌搜索解决方案,不幸的是,他们都没有为我工作。有谁知道如何解决这个问题? 在此先感谢..

+0

一次制作一百个线程是一个_horrible_想法。 – SLaks 2010-11-14 23:29:38

+0

我只是测试这个。我对C#仍然很陌生。 – SolidSnake 2010-11-14 23:32:22

+0

你可能会误解线程。您的代码会创建一百个线程(尝试)同时增加进度栏。在他们全部(尝试)递增之后,他们都会睡觉,然后退出。 – SLaks 2010-11-14 23:35:35

回答

5

不能从非UI线程的UI元素进行交互。 你需要使用如下代码

this.BeginInvoke((Action)(() => PROGRESS_BAR.PerformStep())); 
+0

现在我得到这个错误:错误'System.Windows.Forms.ToolStripProgressBar'不包含'BeginInvoke'的定义和没有扩展方法'BeginInvoke'接受类型'System.Windows.Forms.ToolStripProgressBar'的第一个参数可以找到(你是否缺少使用指令或程序集引用?) – SolidSnake 2010-11-14 23:33:25

+0

您可以在窗体本身上调用'BeginInvoke'。 – SLaks 2010-11-14 23:34:49

+1

对不起,只需更改PROGRESS_BAR.BeginInvoke与this.BeginInvoke – 2010-11-14 23:36:58

2

您应该使用BackgroundWorker component及其ProgressChanged事件。

可以调用DoWork处理器(运行在后台线程)内ReportProgress方法,然后更新在ProgressChanged处理进度条(运行在UI线程)。

如果你真的想自己做(没有BackgroundWorker的),你可以调用BeginInvoke

+0

你能展示一些代码示例吗? – SolidSnake 2010-11-14 23:30:41

+1

@ermac:http://msdn.microsoft.com/en-us/library/waw3xexc.aspx – SLaks 2010-11-14 23:32:01

0

你所有的UI交互,包括回调,属性集和方法调用的,必须是在同一个线程。

其中一个回调可以启动另一个线程(或许多线程),但它们不能直接更新UI。处理更新的方式是通过数据属性。我的处理线程会更新进度状态属性。这是通过UI线程读取的,该线程具有用于定期(100ms)更新进度条的定时器。

如果你这样做,你需要锁定任何用来传递状态更新的对象(例如字符串)。