有时您需要在特定线程上运行特定代码,例如winforms。要在UI线程上运行代码,您需要以下内容:
this.BeginInvoke(new MethodInvoker(() =>
{
try
{
//code
}
catch(Exception ex)
{
HandleException(ex);
}
}
SynchornixationContext是另一种做同样事情的方法。
假设我们知道我们需要在UI线程中运行特定代码,并且我们有一种处理此UI线程上抛出的异常的给定方法(BeginInvoke没有阻塞,因此不会传输异常)。我们怎样才能创建一个方法来制作相同的东西但是更简单:
RunOnUIThread(MyMethod);
RunOnUIThread将包含与此代码中第一个示例相同或更少的代码。
是否可以创建这样的方法?如果是这样怎么样?
答案 0 :(得分:0)
public static void InvokeControlAction<t>(t cont, Action<t> action) where t : Control
{
if (cont.InvokeRequired)
{ cont.Invoke(new Action<t, Action<t>>(InvokeControlAction),
new object[] { cont, action }); }
else
{ action(cont); }
}
答案 1 :(得分:0)
你可以写一些很好的扩展方法,比如这个
public static class ControlExtension
{
public static IAsyncResult BeginInvokeWithExceptionHandling(this Control control, Action method, Action<Exception> exceptionHandler)
{
if (control == null) throw new ArgumentNullException("control");
if (method == null) throw new ArgumentNullException("method");
if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler");
return control.BeginInvoke(new MethodInvoker(() =>
{
try
{
method();
}
catch (Exception ex)
{
exceptionHandler(ex);
}
}));
}
public static IAsyncResult BeginInvokeWithExceptionHandling<T>(this Control control, Delegate method, Action<Exception> exceptionHandler, params object[] args)
{
if (control == null) throw new ArgumentNullException("control");
if (method == null) throw new ArgumentNullException("method");
if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler");
return control.BeginInvoke(new MethodInvoker(() =>
{
try
{
method.DynamicInvoke(args);
}
catch (Exception ex)
{
exceptionHandler(ex);
}
}));
}
}
使用方法:
private void HandleException(Exception ex)
{
}
private void MyMethod()
{
}
this.BeginInvokeWithExceptionHandling(MyMethod, HandleException);
注意:由于Delegate.DynamicInvoke
这可能性能稍差,您可以使用强类型代理修复它。值得注意的是,如果control.BeginInvoke
无法找到委托类型,Delegate.DynamicInvoke
也在内部使用{{1}}。
答案 2 :(得分:0)
我根据Sriram的建议结束了这个:
public static void SendToUIThread(Action method, bool UseExceptionHandling = true)
{
if (method == null)
throw new ArgumentNullException("method is missing");
_threadSyncContext.Send(new SendOrPostCallback(delegate(object state)
{
if (UseExceptionHandling)
{
try
{
method();
}
catch (Exception ex)
{
ErrorController.Instance.LogAndDisplayException(ex, true);
}
}
else
method();
}), null);
}
public static void PostOnUIThread(this Control control, Action method, bool UseExceptionHandling = true)
{
if (method == null)
throw new ArgumentNullException("method is missing");
if (control.InvokeRequired)
PostOnUIThread(method, UseExceptionHandling);
else
{
if (UseExceptionHandling)
{
try { method(); }
catch (Exception ex) { ErrorController.Instance.LogAndDisplayException(ex, true); }
}
else
method();
}
}