避免交叉线程操作错误的最简洁和正确的方法?
我不是很擅长代表,我也不知道幕后发生了什么。 从其他线程访问UI项时,我收到cross thread operation
错误。
我想要做的是在Utility
类中编写generics函数,以便我可以将任何方法/代码块传递给函数。 我可以通过以下方式做到:
-
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; } }
-
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; } }
-
public static void Do(Control c, Action action) { try { if (c.InvokeRequired) { c.TopLevelControl.Invoke(action); } else action(); } catch (Exception ex) { //throw ex; } }
-
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; } }
-
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; } }
-
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和2),3和(4,5和6)之间有什么区别? 我的意思是处理/照顾其他人不会的情况是什么?
-
什么是避免
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
。