- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
<分区>
我有一个带有自定义控件的表单。
我的表单中有一个方法:
private void SetEnabledOnControls(bool val)
{
if (InvokeRequired)
{
Invoke((Action<bool>)SetEnabledOnControls, val);
}
else
{
//do the work - iterate over child controls,
//and they iterate over their children, etc...
}
}
在 else
分支上的方法中,我得到了提到的异常:跨线程操作无效:控件“txtNumber”从创建它的线程以外的线程访问。
我的场景实际上有点复杂 - 我只是将其推断为示例。实际发生的事情是我正在使用 WorkflowFoundation - 我有 StateMachineActivity (CTP1) 在 WorkflowApplication 中运行(在它自己的线程中运行),我订阅了它的事件,然后我从那里调用 SetEnabledOnControls
。此外,我正在使用书签来恢复我的工作流程(另外,旁边有 MEF,不涉及场景)。
所有这些都与我对 InvokeRequired 的明显误解无关 - 如果 InvokeRequired 为假,我怎么可能出现跨线程异常?我不“手动”创建任何控件——它们都在设计师放置的 Initialize() 中。
任何人都可以阐明这一点吗?
谢谢!
编辑根据 GWLlosa 的建议,我使用 System.Threading.Thread.CurrentThread.ManagedThreadId
跟踪了 ThreadId。现在出现了奇怪的部分……Initialize() 中的线程 ID 为 10。在传递前两个状态之间,它带有 ID 13 - InvokeRequired 为真,并且它被正确调用。但是,在第二个状态之后,当它进入 SetEnabledOnControls
时它又是 13,但是这次 InvokeRequired 是 false!怎么来的!?当然,后来它无法更改子控件(不足为奇)。会不会是表单以某种方式改变了它所在的线程??
编辑 2现在我调用:
if (IsHandleCreated)
{
Invoke((Action<bool>)SetEnabledOnControls, val);
}
并且它有 IsHandleCreated
为真,但仍然失败了 devSpeed pointed at .
编辑 3FACEPALM :) 恢复状态的按钮之一最初是表单的 CancelButton。当它从属性中删除时,codebihind 仍然有它的 DialogResult=Cancel - 所以我的表单确实正在关闭,当然它缺少句柄所以 InvokeRequired 没有返回正确的信息,因此错误.
谢谢大家!我今天学到了一个新东西:)
我是一名优秀的程序员,十分优秀!