如果应用程序设计为多线程,则可能会发生跨线程,因此您需要使用 InvokeRequired 检查它,并且在 UI 线程上使用您正在调用 re-Invoke() 本身的方法,或者抛出异常将指示代码使用不当。请记住,在某些情况下 InvokeRequired 将是错误的(主要是当窗口没有句柄或正在/已被处置时);防止这些情况的最好方法是不要在窗口初始化过程中比 Load() 事件处理程序更早地启动线程,并通过取消窗口创建的后台线程并等待它们关闭来处理 Closing() 事件。
如果应用程序不是多线程的(您没有设置 BackgroundWorkers、TPL 操作、BeginInvoke()ing 委托或 Start()ing 线程),则没有必要。但是,对 InvokeRequired 的调用非常便宜(其背后的逻辑基本上是检查 WinAPI 函数 GetThreadId 和 GetWindowThreadProcessId 返回相同的值),因此如果您预计程序被重组为多线程,则调用方法的以下模式很简单足以实现:
//no return value, no parameters; ShowWindow(), HideWindow(), etc
//Understand that many built-in control methods are not virtual and so you can't
//override them to do this; you must either hide them or ensure the caller is
//checking for cross-threading.
public void MyWindowMethod()
{
if(InvokeRequired)
this.Invoke(new Action(MyWindowMethod));
else
{
//main logic
}
}
//Input but no return; SetTitle("My Title")
public void MyWindowMethod2(string input)
{
if(InvokeRequired)
this.Invoke(new Action<string>(MyWindowMethod2), input);
else
{
//main logic
}
}
//inputs and outputs; custom methods, advanced graphics
public string MyWindowMethod3(string input)
{
if(InvokeRequired)
return (string)(this.Invoke(new Func<string, string>(MyWindowMethod3), input));
//No else required; the return makes it redundant
//main logic
}