C# 处理来自BeginInvoke的异常的方法?

C# 处理来自BeginInvoke的异常的方法?,c#,.net,multithreading,C#,.net,Multithreading,有时您需要在特定线程上运行特定代码,例如winforms。要在UI线程上运行代码,您需要以下内容: this.BeginInvoke(new MethodInvoker(() => { try { //code } catch(Exception ex) { HandleException(ex); } } RunOnUIThread(MyMethod); SynchornixationContext是做同样事情的另一种方

有时您需要在特定线程上运行特定代码,例如winforms。要在UI线程上运行代码,您需要以下内容:

this.BeginInvoke(new MethodInvoker(() =>
{
   try
   {
       //code
   }
   catch(Exception ex)
   {
       HandleException(ex);
   }
}
RunOnUIThread(MyMethod);
SynchornixationContext是做同样事情的另一种方式

假设我们知道我们需要在UI线程中运行特定的代码,并且我们有一种特定的方法来处理在该UI线程上引发的异常(BeginInvoke没有阻塞,因此不会传输异常)。我们如何才能创建一个方法,使同样的事情,但更简单,像这样:

this.BeginInvoke(new MethodInvoker(() =>
{
   try
   {
       //code
   }
   catch(Exception ex)
   {
       HandleException(ex);
   }
}
RunOnUIThread(MyMethod);
RunOnUIThread将包含与此代码中第一个示例相同或更少的代码

有可能创建这样的方法吗?如果是这样的话,怎么做?

公共静态void invokeControlion(t cont,Action Action)其中t:Control
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); }
}
{ 如果(续调用要求) {cont.Invoke(新操作(InvokeControlAction), 新对象[]{cont,action};} 其他的 {行动(续);} }

您可以编写一些很好的扩展方法,如下所示

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);
            }
        }));
    }
}

注意:由于
Delegate.DynamicInvoke
这可能会稍差一些,您可以使用强类型委托修复它。还值得注意的是,
control.BeginInvoke
也在内部使用
Delegate.DynamicInvoke
,如果它找不到委托类型是什么。

我根据Sriram的建议结束了upp:

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();
            }
        }

谢谢,但是代码还是太多了,我只想调用RunOnUIThread(MyMethod);您当然可以这样做,但是当出现异常时您想做什么呢?我需要运行与第一个示例中相同的代码。因此,请尝试/catch并在catch中处理异常(此案例记录到数据库)@Banshee更新了我的答案,使其代码更少。很好,非常感谢!我会尽快尝试的。谢谢,但是代码还是太多了,我只想调用RunOnUIThread(MyMethod);