从正在运行的线程C#更改窗体上的属性

时间:2012-10-03 07:30:34

标签: c# multithreading variables

我发现运行一个线程在很大程度上与主应用程序隔离开来。您无法更改变量(在您的类中全局声明),并且您无法通过在线程中为它们提供新值来更改表单属性或任何内容。

当一个线程运行时,你将如何从线程内部更改标签中的文本?

我不认为锁定值是必要的,因为它没有在主程序中使用,因此不会发生死锁。

我尝试过,失败了。

拥有全局变量(int = 0)

运行测试线程将变量更改为5.

当我想在我的线程(messagebox.show(int.tostring())中显示该数字时,var仍为0

您如何在线程中更改主表单中的内容?

代码

创建我没有使用的线程的代码就是这个。

        Thread threadA = new Thread(new ThreadStart(DoWork));
        threadA.Start();

当我使用这种方式时,我收到错误

“跨线程操作无效:控制'button1'从其创建的线程以外的线程访问”

当我尝试在我的帖子上编辑或更改某些内容时。

所以我使用了这段代码。

lbldirectory是我的部分类的名称。

            // StartFileCheckProcess();
            workerObject = new lbldirectory(); 
            workerThread = new Thread(workerObject.DoWork);

            // the worker thread.
            workerThread.Start();

DoWork是我的课程,我尝试更改表格上的属性。

这是DoWork类。它真的是一个简单的类,但它只是为了理解为什么会发生这种情况,并且让其他人只是理解为什么以及如何克服它的原因。

public void DoWork()
        {
            button1.Text = "Hello there";
        }

因此运行线程,线程工作,它只是无法更改我的表单上的任何内容。

修改后的答案 (由Tudor和Konstantin Vasilcov提供)

点击按钮事件。

var t = new Thread(TEST);
    t.Start();

线程启动的类

private void TEST()
            {
                for (int i = 0; i < 10; i++)
                {
                    lbl_CurrentFile.BeginInvoke(
                    ((Action)(() => lbl_CurrentFile.Text = i.ToString())));
                    Thread.Sleep(1000);
                }
            }

成功更改线程内标签的文本

2 个答案:

答案 0 :(得分:7)

好的,这里有两件事需要注意:

1.更改GUI控件:只有GUI线程才能更改控件。其他线程需要通过Invoke / BeginInvoke将其更新转发到GUI线程,例如:

 var t = new Thread(
    o => 
    {
         textBox.BeginInvoke(
             ((Action)(() => textBox.Text = "text")));
    });

2.更改标量值或引用:这通常可以毫无问题地完成,但要警惕数据争用。

答案 1 :(得分:6)

如果您需要从后台线程访问GUI,则需要使用Control.Invoke方法:

public void DoWork()
{
    button1.Invoke(new Action(() =>
    {
        button1.Text = "Hello there";
    }));            
}

如果您在多个线程之间共享一些变量,则每次其中一个线程访问共享变量时,必须明确地使用其中一个同步技术进行保护。我想你可以找到大量必要的信息:Thread Synchronization (C# Programming Guide)