处理BeginInvoke异常的方法
本文关键字:方法 异常 BeginInvoke 处理 | 更新日期: 2023-09-27 18:02:14
有时您需要在特定线程上运行特定代码,例如winforms。为了让代码在UI线程上运行,你需要这样的东西:
this.BeginInvoke(new MethodInvoker(() =>
{
try
{
//code
}
catch(Exception ex)
{
HandleException(ex);
}
}
SynchorixationContext是做同样事情的另一种方式。
假设我们知道我们需要在UI线程中运行特定的代码,并且我们有一种特定的方法来处理在这个UI线程上抛出的异常(BeginInvoke没有阻塞,因此不会传输异常(。我们如何才能创建一种方法,使同样的事情变得更简单:
RunOnUIThread(MyMethod);
RunOnUIThread将包含与此代码中的第一个示例大致相同的代码。
有可能创建这样的方法吗?如果是,怎么办?
您可以编写一些不错的扩展方法,比如这个
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
。
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); }
}
CodeProject参考
根据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();
}
}