簡體   English   中英

使用.NET任務並行庫捕獲錯誤

[英]Catching errors with .NET 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();  

}

更好的選擇是將部分代碼重構為一個單獨的方法,返回一個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;
    }
}

重構代碼比將它們全部放在同一個地方更好。如果您需要做的就是記錄它,最好在代理中捕獲異常。

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

但是如果你有另一個方法DoSomethingElse()可能會受到Task的結果的影響。它最好包裝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)
     {

     }
}

與任何它取決於它。

我會說將Task.Run()部分重構成一個單獨的異步Task方法,就像Sriram Sakthivel的回答一樣,通常是一件好事。 它避免在版本2中使用lambda中捕獲的bool,它允許您編寫更簡潔地表達意圖的代碼。

也就是說,我會仔細考慮“catch all - > log - > ignore”模式是否是你想要的。 通常:捕獲特定的異常並專門處理它們。 對於所有其他異常,您可以記錄它們,但仍然使用“throw”重新拋出它們。 或者“拋出新的MoreSpecificException(originalException);”。

考慮到這一點,我建議如果你執行catch catch all方法,你應該像版本1一樣完成catch。

為了保持高可讀性,使代碼簡潔明了,並明確處理異常,我會這樣寫:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM