gpt4 book ai didi

c# - 为什么我们不能从工作线程更新 UI?与其他变量/对象相同

转载 作者:太空狗 更新时间:2023-10-30 00:37:48 26 4
gpt4 key购买 nike

想问一个愚蠢的问题,但我想知道答案。我不需要任何代码来从工作线程更新 UI 我知道如何从工作线程/线程池更新 UI。

我想知道为什么我们会收到此错误“跨线程操作无效:从创建它的线程以外的线程访问控件”。每当任何工作线程尝试更新 UI 控件时?为什么当工作线程访问由主线程创建的对象并且没有 UI 交互时不会出现此错误?

看下面的例子

public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
}

TextBox textbox2 = null;
List<int> collection = new List<int>();
public Form1()
{
InitializeComponent();
textbox2 = new TextBox();
}
public void UpdateTextBox()
{
collection.Add(Thread.CurrentThread.ManagedThreadId);
textbox2.Text = "hi, ThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString();
panel1.Controls.Add(textbox2);//If remove this line... will work with worker thread.
}
private void btnMainThread_Click(object sender, EventArgs e)
{
UpdateTextBox();
}
private void btnWorkerThread_Click(object sender, EventArgs e)
{
Thread t1 = new Thread(UpdateTextBox);
t1.Start();//Will get error. why?
}
}

我们如何为我的“collection”变量应用相同类型的重构。?

最佳答案

答案 - 我认为 - 你正在寻找(为什么以及如何引发异常)是因为 Control 类的 Handle 中有显式代码属性将检查要访问该属性的代码是否在创建控件(用户界面线程)的同一线程上运行。

您可以查看Handle 属性的引用来源here .实际的线程检查发生在 InvokeRequired 属性的实现中,您还可以检查 here .

.net Framework 的早期版本不包括此检查,因此从不同的线程访问用户界面非常容易。我们不能不应该这样做的原因是因为有很大一部分 Win32 API 代码库不是线程安全的,所以从单个线程调用它是唯一的方法保证在多线程应用中不会出现并发问题。

Handle 属性将在控件内部调用与其交互的任何相关 Win32 API 函数之前被访问(您可以将句柄视为 WIN32 API 中的“this”引用),因此它是集中跨线程检查的一个很好的候选者。

如果我从您的评论中理解正确,您希望在工作线程尝试更新某个值(不一定是用户界面元素)时模拟相同的行为(引发异常)“拥有”不同的线程。在这种情况下,您可以采用框架正在使用的相同策略

如果您分析 InvokeRequired 的代码,它只是将当前线程的 ID 与 SafeNativeMethods.GetWindowThreadProcessId() 返回的值进行比较,并返回 true 如果不匹配。这会导致在 Handle 属性的 getter 访问器中引发跨线程异常。 在您的情况下,您可以存储允许访问变量或资源的线程的 ID,如果此存储的 ID 与尝试访问 protected 值的线程的 ID 不匹配,则手动引发异常。

关于c# - 为什么我们不能从工作线程更新 UI?与其他变量/对象相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44482721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com