c# - 访问 UI 控件时是否应始终使用 Control.InvokeRequired

标签 c# .net winforms clr ui-thread

我们正在使用 WinForms (3.5) 构建一个 .NET 应用程序。

我最近添加了一项新功能,在访问某些控件时开始遇到奇怪的行为。问题是一些 UI 控件访问只是停止了执行(没有看到异常)。

在仔细检查(使用 WinDbg)后,我意识到控件正在从 ThreadPool 线程更新,并且抛出了 CrossThreadMessagingException。

我的问题是 - 是否有关于如何规避此类行为的良好做法?

这将非常麻烦,但也可能无法使用 Control.Invoke 方法包围访问 UI 控件的每个代码位置。

我如何将我的代码划分为不应使用 Invoke 的“安全”代码和应该使用的代码?

最佳答案

如果应用程序被设计为多线程,则可能会发生跨线程,因此您需要使用 InvokeRequired 来检查它,或者使用您使用的方法在 UI 线程上调用 re-Invoke() 本身,或者抛出一个异常,表明代码使用不当。请记住,在某些情况下 InvokeRequired 将为 false(主要是当窗口没有句柄或正在处理/已处理时);防止这些情况的最佳方法是不要在窗口初始化过程中比 Load() 事件处理程序更早地启动线程,并通过取消窗口创建的后台线程并等待它们关闭来处理 Closing() 事件。

如果应用程序不是多线程的(您没有设置 BackgroundWorkers、TPL 操作、BeginInvoke()ing 委托(delegate)或 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   
}

关于c# - 访问 UI 控件时是否应始终使用 Control.InvokeRequired,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12042681/

相关文章:

c# - WCF 服务客户端 : Customized soap envelope not being sent on the wire

c# - WPF 应用程序 : Controls look like . NET 2.0 中的 WinForms 对话框

c# - 带有 Entity Framework 的 ASP.NET : EF does not generate identity automatically

c# - wpf自定义控件: draggable/resizable rectangle within another rectangle

java - 是否有与可编写脚本的 Java applet 等效的 .Net 技术? (针对特定用例)

c# - 如何使用 C# 获取给定路径(可以是目录或文件,甚至是完整路径)的完整路径?

c# - 是否可以从 c# winforms 调用 Javascript 方法?

c# - 启动隐藏的 Windows 窗体应用程序 - 高内存使用率?

c# - 适用于由线集合定义的 map 的寻路算法

c# - 构建期间未知的命名空间(但智能感知知道)