为什么BackgroundWorker可以修改UI组件?

isp*_*iro 1 c# backgroundworker

我正在更改Text按钮BackgroundWorker,它可以工作.我以为应该抛出异常.为什么不呢?

为什么我没有得到Cross-thread operation not valid: ... accessed from a thread other than the thread it was created on.

编辑:谢谢大家.

也许原因是Thread.Sleep(1000);在UI上有一个:

public Form1()
{
    InitializeComponent();

    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerAsync();
    Thread.Sleep(1000);
}

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    button1.Text = "a";
}
Run Code Online (Sandbox Code Playgroud)

但是,我注意到以下代码运行良好,尽管影响了UI(间接).

public partial class Form1 : Form
{
    int i;

    public Form1()
    {
        InitializeComponent();

        i = 1;
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerAsync();
        for (int j = 0; j < 100000000; j++) ;
        button1.Text = i.ToString();
    }

    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        i = 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么?

Bro*_*ass 5

一旦完成工作,后台工作程序调用的回调函数(BackgroundWorker.RunWorkerCompleted)为了您的方便 - 已经使用UI线程调度程序.

编辑:

@ispiro:无法保证第二个示例中的代码始终有效 - 您仍然可以对变量进行跨线程更新,i因此您应该声明它volatile以确保它始终正确更新.

第一码的原因不应该工作是在.NET框架可以帮助你检测这种跨线程访问.正如@Greg D指出的那样,这可以被禁用(这绝对是禁止的).有关更多信息,请查看此MSDN页面:

.NET Framework可帮助您以非线程安全的方式检测何时访问控件.当您在调试器中运行应用程序时,除了创建控件的线程之外的线程尝试调用该控件时,调试器会引发一个InvalidOperationException,并显示消息"从该线程以外的线程访问控制控件名称"创建于."

在调试期间以及在某些情况下在运行时可靠地发生此异常.调试在.NET Framework 2.0之前使用.NET Framework编写的应用程序时,可能会看到此异常.强烈建议您在看到此问题时解决此问题,但可以通过将CheckForIllegalCrossThreadCalls属性设置为false来禁用它.这会使您的控件像在Visual Studio .NET 2003和.NET Framework 1.1下运行一样运行.