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