当前位置:  开发笔记 > 程序员 > 正文

不可能(我多讨厌使用这个词)交叉线程错误?

如何解决《不可能(我多讨厌使用这个词)交叉线程错误?》经验,为你挑选了2个好方法。

任何人都可以解释一下这可能发生的原因吗?

我完全了解编程时考虑到线程安全性,你可以看到我通过表单InvokeRequired检查UI更新,检查一切,一切都工作正常,没有任何修改来打破这个,我知道,现在突然就像我正在编写应用程序的其他部分(可能在一个阶段添加到此方法?我只是不记得了)我不好意思,收到此错误:

替代文字

首先,如果InvokeRequired = true,那应该意味着执行了BeginInvoke(),方法是[队列]重新调用,而InvokeRequired应该等于false?

我不应该收到这个例外,因为它应该照顾吗?

希望听到一些多线程大师:)

格雷厄姆



1> Chris Peters..:

我怀疑InvokedRevoked可能会骗你.WinForm控件推迟创建Control的底层Win32 HWND,直到方法调用实际需要它为止.如果尚未创建HWND,InvokeRequired将返回false.

有关详细说明,请参阅:"神秘挂起或InvokeRequired的大骗局"

如果后台线程在UI线程导致控件懒惰地创建其HWND 之前查询InvokeRequired ,则InvokeRequired将(错误地)告诉您的后台线程它不需要使用Invoke()将控制权传递回UI线程.然后后台线程访问Control,BAM!"InvalidOperationException:跨线程操作无效!"

UI线程可以手动强制Control创建其HWND句柄,因此Control.InvokeRequired将知道UI线程是Control的所有者:

Control control = new Control();
IntPtr handle = control.Handle; // if you ask for HWND, it will be created



2> Jonathan C D..:

大多数人看到这个错误并看到一件事,"你没有从主UI线程访问这个控件." 实际上,如果需要,您可以拥有100个UI线程(此行为未定义,但受支持).机会是panelMain是在不同的线程上创建的(this); 我看不到代码 - 但看起来你正在你的工作者/线程中创建它.

要确认行为,请尝试以下操作:

Action addAction = new Action (
   new delegate { panelMain.Controls.Add(UCLoadingScreen); } )
if(panelMain.InvokeRequired)
{
   panelMain.Invoke(addAction); // Breakpoint here.
}
else
{
   addAction();
}

准备好一个不同的错误(一个不同的线程上的子控件,它的父母,不知道你会得到什么错误,但我很确定你会.)这不是解决方法.

然而工厂会解决这个问题:

public void CreateControl() where T : new()
{
    if(InvokeRequired)
    {
        return (T)Invoke(new Func(CreateControl()));
    }
    return new T();
}

编辑:panelMain可能不是线程'违规者',正如我所说,来自不同线程的父控制导致高度不确定的行为.确保所有控件都是在主窗体的主题的上下文中创建的.

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有