我的表單上有我的自定義控件。跨線程操作無效,即使使用InvokeRequired
我在表格的方法:
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
分支我得到的提到例外的方法中:
Cross-thread operation not valid: Control 'txtNumber' accessed from a thread other than the thread it was created on.
我的情況實際上是更復雜一點 - 我只是推斷這個例子。實際上,我使用的是WorkflowFoundation - 我在WorkflowApplication(運行在它自己的線程中)中運行了StateMachineActivity(CTP1),我訂閱了它的事件,並從那裏打電話給SetEnabledOnControls
。此外,我正在使用書籤來恢復我的工作流程(並且,還有一邊是MEF,並未涉及該場景)。
所有這一切都與我對InvokeRequired的顯而易見的誤解無關 - 如果InvokeRequired爲false,我有跨線程異常怎麼可能?我沒有手動創建任何控件 - 它們都在由設計者放置的Initialize()中。
任何人都可以對此有所瞭解嗎?
謝謝!
編輯 使用GWLlosa建議,我已經使用System.Threading.Thread.CurrentThread.ManagedThreadId
跟蹤的ThreadId。現在出現了奇怪的部分... Initialize()中的線程ID爲10.在傳遞前兩個狀態之間,它帶有Id 13 - InvokeRequired爲true,並且它調用正確。但是,在第二個狀態之後,當它進入SetEnabledOnControls
時它又是13,但這次InvokeRequired是錯誤的!怎麼來的!?後來,當然,它不能改變兒童控制(不奇怪)。難道是表單以某種方式改變了它生活的線程?
EDIT 2 現在,我有打電話:
if (IsHandleCreated)
{
Invoke((Action<bool>)SetEnabledOnControls, val);
}
,它有IsHandleCreated
爲真,但還是失敗,什麼devSpeed pointed at。
編輯3 捂臉 :)一說是恢復狀態的按鈕是在爲形式的第一CancelButton。當它從屬性中移除時,codebihind仍然具有DialogResult =取消它 - 所以我的表單確實正在關閉,當然它丟失了句柄,因此InvokeRequired沒有返回正確的信息,因此錯誤。
謝謝大家!我今天學到了一件新東西:)
確實我在最後碰到它了......有用的鏈接;) – veljkoz 2010-12-17 12:56:18