简体   繁体   English

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

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

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

The reason MSDN gives for not allowing this: MSDN不允许这样做的原因:

Access to Windows Forms controls is not inherently thread safe. 访问Windows Forms控件本质上不是线程安全的。 If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state . 如果您有两个或多个线程来操纵控件的状态, 则可以将控件强制变为不一致的状态 Other thread-related bugs are possible as well, including race conditions and deadlocks. 其他与线程相关的错误也是可能的,包括竞争条件和死锁。 It is important to ensure that access to your controls is done in a thread-safe way. 确保以线程安全的方式完成对控件的访问非常重要。

So technically I could be possible (and maybe they left it out by-design), but the problem is the underlying code from Microsoft isn't thread safe. 因此从技术上讲,我是有可能的(也许他们是在设计时将其遗漏了),但问题是Microsoft的基础代码不是线程安全的。 This has probably to do with the inner workings of Windows and it's lack of thread safety in their Win32 UI model. 这可能与Windows的内部工作方式有关,并且Win32 UI模型中缺乏线程安全性。

You cant make changes to the GUI from any other thread but the GUI thread(main thread). 您不能从GUI线程(主线程)以外的任何其他线程对GUI进行更改。 That being said you can read the data from controls (textboxes etc) from whatever thread without problems if you want to make changes to controls from another thread you need to use something like this: 话虽如此,如果您想从另一个线程更改控件,则可以从任何线程读取控件(文本框等)中的数据,而无需使用以下操作:

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

The downside of this is that now the thread from which you are calling this is getting blocked until this change to the textbox is done. 不利的一面是,现在您正在调用的线程被阻塞,直到完成对文本框的更改为止。 This isnt a problem if you are updating your controls from your thread not often but if you want to do it often you need to create a 3rd thread that handles the updates depending on what the worker thread is doing. 如果您不经常从线程中更新控件,但这不是问题,但是如果您想经常执行此操作,则需要创建一个第3个线程来处理更新,具体取决于工作线程在做什么。 Something like this 像这样

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();

Now the workthread is working at full speed without getting blocked by the UI and the UI is still getting updated on the current status 现在,工作线程正在全速运行,而不会被UI阻塞,并且UI仍在更新当前状态

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

相关问题 为什么我只能从BackgroundWorker访问某些UI控件属性? - Why can I access only some UI control properties from BackgroundWorker? 为什么从另一个线程更新控件的某些属性是安全的? - Why it is safe to update some properties of a control from another thread? 为什么用户控件类访问不能从另一个线程安全? - why isn't user-control class access not safe from another thread? 为什么我无法从其他文件访问表单属性? - Why I can't reach form properties from another file? 你可以从另一个线程访问UI元素吗? (没有设定) - Can you access UI elements from another thread? (get not set) 我似乎无法从列表视图模板中的代码访问我的ui属性 - I can't seem to access my ui properties from my codebehind in a listview template 为什么不能在用户控件构造函数中启动线程? - Why can't I start a thread within a user control constructor? 为什么不能直接访问已分配给WinForms Control.Tag属性的自定义对象的属性? - Why can't I directly access the properties of a custom object that I've assigned to a WinForms Control.Tag property? 如何显示另一个UI线程上的对话框 - How can I show dialog on UI thread from another 如果线程没有修改该元素,是否可以从另一个线程访问UI元素? - Is it possible to access a UI element from another thread if the thread doesn't modify that element?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM