[英]Catching errors with .NET Task Parallel Library
以下是我嘗試捕捉錯誤的兩種選擇,它們似乎都做同樣的事情......但是比另一種更好,為什么呢?
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();
}
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.