处理Task.ContiueWith中发生的异常

时间:2015-06-25 06:26:38

标签: c# exception async-await task-parallel-library task

我正在研究wpf,我编写了以下代码,以便在从Web服务获取数据时显示异常。

有两种操作方法,第一种是调用远程服务,第二种是在获得结果时更新UI对象。

当在第一个动作(初始)期间发生异常时,我正在获得异常框,但是当第二个动作(成功)中发生异常时,它们被忽略并且没有发生任何事件。事件断点没有在最后一行继续命中。

我想知道发生了什么和最好的解决方案。这种类型的异常不能全局处理吗?

private void ExecuteSafely(string message, Action intial, Action successAction)
{

    var task = Task.Factory.StartNew(intial);
    task.ContinueWith(t =>
    {
        if (t.Exception != null)
        {
            HandleException(t.Exception);
        }
        else
        {
            successAction.Invoke();
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

2 个答案:

答案 0 :(得分:2)

  

但是当第二个动作(成功)发生异常时,它们会被忽略   并没有任何反应

因为您没有将代码包装在try-catch块中,因此异常不会被处理,并且会被延续任务吞没。

要抓住它,请进行包装:

private void ExecuteSafely(string message, Action initial, Action successAction)
{
    var task = Task.Factory.StartNew(initial).ContinueWith(t =>
    {
        if (t.Exception != null)
        {
            HandleException(t.Exception);
        }
        else
        {
            try
            {
               successAction();
            }
            catch (Exception e)
            { 
                // Handle your exception.
            }
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

如果您使用的是.NET 4.0,那么在Task的最终确定期间最终会抛出被吞噬的异常。

如果您使用的是.NET 4.5,async-await将不那么详细:

private async Task ExecuteSafelyAsync(string message, 
                                      Action initial, 
                                      Action successAction)
{
    try
    {
        var task = await Task.Run(initial);
        successAction();
    }
    catch (Exception e)
    {
        // You get here if either Task.Run or successAction throws
    }
}

当你调用它时:

await ExecuteSafelyAsync("hello", initial, success);    

答案 1 :(得分:0)

当successAction抛出异常时,UI线程无法捕获异常,因为在UI线程上没有调用successAction。

如果您正在使用.net 4.5,我认为您应该使用async / await,例如:

private async void ExecuteSafely(string message, Action intial, Action successAction)
{
    try
    {
        await Task.Factory.StartNew(intial);
        successAction.Invoke();
    }
    catch (Exception e)
    {
        HandleException(e);
    }
}