Invoke和BeginInvoke之間的區別在於前者是同步的(等待完成),而後者是異步的(有點讓人失望)。但是,兩者都通過向UI消息循環發佈消息來工作,這將導致在獲取該消息時執行委託。
InvokeRequired屬性決定您是否需要調用,或者它是否已經在正確的線程上,而不是您想要同步還是異步調用。如果InvokeRequired爲false,則(理論上)已經在UI線程上運行,並且可以直接執行同步操作(如果需要異步觸發它們,則仍然是BeginInvoke)。這也意味着,如果InvokeRequired爲false,則不能使用Invoke,因爲當前線程上的消息循環無法繼續。所以這是你上面的代碼的一個大問題,但不一定是你報告的錯誤。你可以在的這兩種情況下實際使用BeginInvoke,如果你注意遞歸調用,等等。
但是,您不能使用任何一個沒有窗口句柄。如果Form/Control已經實例化但未初始化(即在它首次顯示之前),它可能還沒有處理。並且句柄被Dispose()清除,例如在Form關閉之後。無論哪種情況,InvokeRequired都會返回false,因爲不可能在沒有句柄的情況下調用。您可以檢查IsDisposed,並且還有一個屬性IsHandleCreated,它更具體地測試句柄是否存在。通常,如果IsDisposed爲true(或者IsHandleCreated爲false),則希望將其放入特殊情況,例如簡單地放棄不適用的操作。
所以,你想要的代碼可能更象:
if (IsHandleCreated)
{
// Always asynchronous, even on the UI thread already. (Don't let it loop back here!)
BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);
return; // Fired-off asynchronously; let the current thread continue.
// WriteToForm will be called on the UI thread at some point in the near future.
}
else
{
// Handle the error case, or do nothing.
}
或許:
if (IsHandleCreated)
{
// Always synchronous. (But you must watch out for cross-threading deadlocks!)
if (InvokeRequired)
Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);
else
WriteToForm(finished, numCount); // Call the method (or delegate) directly.
// Execution continues from here only once WriteToForm has completed and returned.
}
else
{
// Handle the error case, or do nothing.
}
不知道更多關於這個問題,它聽起來就像你調用一個事件完全創建表單前/初始化,或在某些時候另一個線程它不該」不要。 –
如果運行(System.Timers或的System.Threading)任何計時器,檢查它們是否正在導致這個代碼尚未完全構造或設置在表格上運行。 –
這段代碼在哪裏,什麼方法或事件處理程序? – Kev