避免交叉线程操作错误的最简洁和正确的方法?

我不是很擅长代表,我也不知道幕后发生了什么。 从其他线程访问UI项时,我收到cross thread operation错误。

我想要做的是在Utility类中编写generics函数,以便我可以将任何方法/代码块传递给函数。 我可以通过以下方式做到:

  1.  delegate void UpdateGui(Control c, Action action); public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { UpdateGui updaterdelegate = new UpdateGui(Do); c.TopLevelControl.Invoke(updaterdelegate, new object[] { c, action }); } else action(); } catch (Exception ex) { //throw ex; } } 
  2.  public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { c.TopLevelControl.Invoke((Action)delegate { Do(c, action); }); } else action(); } catch (Exception ex) { //throw ex; } } 
  3.  public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { c.TopLevelControl.Invoke(action); } else action(); } catch (Exception ex) { //throw ex; } } 
  4.  public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { c.TopLevelControl.Invoke(new MethodInvoker(() => action())); } else action(); } catch (Exception ex) { //throw ex; } } 
  5.  public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { c.TopLevelControl.Invoke(new MethodInvoker(delegate { action(); })); } else action(); } catch (Exception ex) { //throw ex; } } 
  6.  public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { c.TopLevelControl.Invoke((MethodInvoker)delegate { action(); }); } else action(); } catch (Exception ex) { //throw ex; } } 

我认为方法1和方法2基本相同,并且4,5和6也是如此。 我的问题是:

  1. 方法(1和2),3和(4,5和6)之间有什么区别? 我的意思是处理/照顾其他人不会的情况是什么?

  2. 什么是避免cross thread operation错误的正确方法,在某种意义上它处理所有情况,最好是简洁和可读?

上面的“第三种”方法(仅使用Action )更简单,更有效。 您使用delegate其他方法创建一个单独的方法(通过delegate关键字的匿名方法),然后调用您的原始委托( action参数),这是不必要的。

第3个选项只是直接使用传入的Action ,这更简单。

第一个选项是类似的,但在这种情况下,您传递的是不必要的值( Control )以及必须定义自定义委托(尽管您可以使用Action代替)。 由于未使用Control,因此没有理由添加此复杂性。

旁注 – 当你在exception处理程序中重新抛出时,最好只使用throw; (而不是throw ex; ),因为这将正确保留堆栈跟踪:

 catch (Exception ex) { // Do whatever, ie: logging throw; } 

如果您不打算登录,并且只是计划重新抛出,则可以完全省略try / catch