使用.NET任务并行库捕获错误

时间:2015-09-16 05:00:43

标签: c# exception error-handling task-parallel-library

以下是我尝试捕捉错误的两种选择,它们似乎都做同样的事情......但是比另一种更好,为什么?

替补1:

private async void BtnClickEvent(object sender, RoutedEventArgs e)
{

    try
    {
        Task t = Task.Run(() =>
            {
                _someObj.SomeMethod();
            });
        await t; //wait here, without blocking...
    }
    catch (Exception ex)
    {
        string errMsg = ex.Message + Environment.NewLine;
        errMsg += "some unhandled error occurred in SomeMethod";
        Log(errMsg);

        return; //<-- bypass below code on error...
    }

    //other code below... does not execute...
    DoSomethingElse();

}

替补2:

private async void BtnClickEvent(object sender, RoutedEventArgs e)
{

    bool errOccurred = false;

    Task t = Task.Run(() =>
        {
            try
            {
                _someObj.SomeMethod();
            }
            catch (Exception ex)
            {
                string errMsg = ex.Message + Environment.NewLine;
                errMsg += "some unhandled error occurred in SomeMethod";
                Log(errMsg);

                errOccurred = true;

            }//end-Catch
        });
    await t; //wait here, without blocking...
    if (errOccurred) return; //<-- bypass below code on error...

    //other code below... does not execute...
    DoSomethingElse();  

}

3 个答案:

答案 0 :(得分:1)

更好的选择是将部分代码重构为一个单独的方法,返回一个bool,指示是否继续。

private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
    bool success = await SomeMethodAsync();
    if (!success)
    {
        return;
    }

    //other code below... does not execute...
    DoSomethingElse();
}

private async Task<bool> SomeMethodAsync()
{
    try
    {
        await Task.Run(() => _someObj.SomeMethod());
        return true;
    }
    catch (Exception ex)
    {
        string errMsg = string.Format("{0} {1}some unhandled error occurred in SomeMethod",
        ex.Message, Environment.NewLine);
        Log(errMsg);          

        return false;
    }
}

答案 1 :(得分:0)

重构代码比将它们全部放在同一个地方更好。如果您需要做的就是记录它,最好在代理中捕获异常。

private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
  await Task.Run(() =>
        {
            try
            {
               DoSomeWork();
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        });
}

但是,如果你有另一个方法DoSomethingElse()可能会受到任务结果的影响。最好将try catch包裹在await

附近
private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
    try
    {
        await Task.Run(() =>
        {
            try
            {
                DoSomeWork();
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        });

        DoSomethingElse();

     }
     catch(Exception ex)
     {

     }
}

答案 2 :(得分:0)

与所依赖的任何事情一样。

我说将Task.Run()部分重构为一个单独的异步任务方法,就像Sriram Sakthivel的回答一样,通常是一件好事。它避免在版本2中使用lambda中捕获的bool,它允许您编写更简洁地表达意图的代码。

那就是说,我会仔细考虑&#34;赶上所有 - &gt; log - &gt;忽略&#34;模式是你想要的。通常:捕获特定的异常并专门处理它们。对于所有其他异常,您可以记录它们,但仍然使用&#34; throw;&#34;重新抛出它们。或者&#34;抛出新的MoreSpecificException(originalException);&#34;。

考虑到这一点,我建议如果你执行catch catch all方法,你应该像版本1那样捕获所有内容。

为了保持高可读性,使代码简洁明了,并明确处理异常,我会这样写:

private async void BtnClick(object sender, RoutedEventArgs e)
{
    try
    {
        if (await TryDoSomethingAsync())
        {
            DoSomeMoreStuff();
        }
    }
    catch (Exception ex)
    {
        // I am sure it is fine that any and all exceptions can be logged and ignored.
        Log(ex);

        // And maybe even notify the user, since I mean, who monitors log files anyway?
        // If something that shouldn't go wrong goes wrong, it's nice to know about it.
        BlowUpInYourFace(ex);
    }
}


private async Task<bool> TryDoSomethingAsync()
{
    return await Task.Run<bool>(() =>
    {
        try
        {
            _myService.DoSomething();
        }
        catch (SomeKnownException ske)
        {
            // An expected exception which is fine to ignore and return unsuccessful.
            Log(ske);
            return false;
        }
        catch (SomeOtherKnownException soke)
        {
            // Expected exception that indicates something less trivial, but could be more precise.
            throw new MyMorePreciseException(soke);
        }

        // Nothing went wrong, so ok.
        return true;
    });
}