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

Pankaj Rawat

感觉像一个愚蠢的问题,但我想知道答案。我不需要任何代码即可从工作线程更新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”变量应用相同类型的重构?

BlueStrat

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

您可以在此处检查Handle属性的参考源实际的线程检查发生在属性的实现内部,您也可以在此处进行检查InvokeRequired

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

Handle在控件内部调用与其相关的任何相关Win32 API函数之前,都将访问属性(您可以将句柄视为WIN32 API中的“ this”引用),因此,对于集中交叉线程检查。

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我们不能在其他线程中更新视图,当我们这样做时,它报告异常,是什么原因

为什么我们不能从逆变型再现

为什么我不能从其他类访问公共变量?

为什么我们不能在Elixir保护子句或宏中使用其他功能?

还有其他原因为什么我们使用填充使序列长度相同?

为什么主线程不能比较其他线程更新的两个变量?

为什么我们可以在开关的其他大小写标签内访问变量?

为什么我们不能从Java中的RequestBody获取文件数据?

为什么我们不能从sql调用过程

为什么不同于类的其他成员,我们为什么需要定义类的静态变量?

为什么我们不能将带有其他参数的{}块传递给Ruby中的方法

如果“反应”是“反应”的默认导出,为什么我们不能使用其他名称代替“反应”

为什么我不能从其他节点IP访问kubernetes容器?

为什么我不能从Vim中的其他程序粘贴和复制?

为什么我们不能直接调用线程#睡眠()lambda函数里面?

为什么我能投的对象?可以将它与其他对象做什么?

在angularjs中,我们如何实现基于其他对象的对象更新?

为什么模式替换不能从单个变量工作?

为什么其他不能正常工作?

为什么我们不能通过变量定义数组大小?

为什么我们不能在INTERFACE的静态块内分配变量?OCA

为什么我们不能声明一个类型为void的变量?

为什么我们不能在C中使用变量作为e的值

为什么我们不能使用scanf直接初始化struct中的变量?

为什么我们不能在声明结构变量名称时使用连字符?

为什么我们不能使用由 DOM getElementsByClassName 选择的变量的 addEventListener ?

如果没有sudo,为什么我们不能以其他用户身份执行命令列表?

为什么我们不能将除字符串以外的其他数据类型的数组传递给Main

为什么我们不能通过.net中的对象访问静态方法