处理BeginInvoke异常的方法?

时间:2014-05-08 09:32:33

标签: c# .net multithreading

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

this.BeginInvoke(new MethodInvoker(() =>
{
   try
   {
       //code
   }
   catch(Exception ex)
   {
       HandleException(ex);
   }
}

SynchornixationContext是另一种做同样事情的方法。

假设我们知道我们需要在UI线程中运行特定代码,并且我们有一种处理此UI线程上抛出的异常的给定方法(BeginInvoke没有阻塞,因此不会传输异常)。我们怎样才能创建一个方法来制作相同的东西但是更简单:

RunOnUIThread(MyMethod);

RunOnUIThread将包含与此代码中第一个示例相同或更少的代码。

是否可以创建这样的方法?如果是这样怎么样?

3 个答案:

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

CodeProject Reference

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