繁体   English   中英

为什么我不能从另一个线程访问UI控件的属性?

[英]Why can't I access properties of an UI control from another thread?

我读到不可能从另一个线程(不仅是GUI,而且还访问所有2个不同的线程)访问UI元素,并且看到了如何解决该问题的代码,但是没有找到解释为什么我不能这样做?

MSDN不允许这样做的原因:

访问Windows Forms控件本质上不是线程安全的。 如果您有两个或多个线程来操纵控件的状态, 则可以将控件强制变为不一致的状态 其他与线程相关的错误也是可能的,包括竞争条件和死锁。 确保以线程安全的方式完成对控件的访问非常重要。

因此从技术上讲,我是有可能的(也许他们是在设计时将其遗漏了),但问题是Microsoft的基础代码不是线程安全的。 这可能与Windows的内部工作方式有关,并且Win32 UI模型中缺乏线程安全性。

您不能从GUI线程(主线程)以外的任何其他线程对GUI进行更改。 话虽如此,如果您想从另一个线程更改控件,则可以从任何线程读取控件(文本框等)中的数据,而无需使用以下操作:

textBox1.Invoke((MethodInvoker)(() =>
{
    textBox1.Text = "text changed from another thread";
}));

不利的一面是,现在您正在调用的线程被阻塞,直到完成对文本框的更改为止。 如果您不经常从线程中更新控件,但这不是问题,但是如果您想经常执行此操作,则需要创建一个第3个线程来处理更新,具体取决于工作线程在做什么。 像这样

List<string> list = new List<string>();
Thread workThread = new Thread(dowork =>
{
    //random work
    for(int a = 0; a< 1000000;a++)
    {
        list.Add(a+" iteration");
        Thread.Sleep(10);
    }
});
workThread .Start();
bool updateThreadWorking = true;
Thread updateThread = new Thread(dowork =>
{
    while(updateThreadWorking)
    {
        while(list.Count > 0)
        {
            listBox.Invoke((MethodInvoker)(() =>
                listBox.Items.Add(list[0]);
            }));
            list.RemoveAt(0);
        }
        Thread.Sleep(200);
    }
});
updateThread .Start();

现在,工作线程正在全速运行,而不会被UI阻塞,并且UI仍在更新当前状态

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM