最近2個月又重回C#懷抱了,昨晚追查一個底層ThreadPool Exception,然後會造成w3wp的Exception, 會造成集區重啟的異常
後來發現有一個非同步呼叫射後不理的部分,並沒有合理的包裝例外,然後又會造成.net framework底層無法Handle的例外
Legacy Code的用法是改一半的非同步呼叫方法
function method1()
{
method2();
}
async Task<ResultObj> function method2()
{
//略
}
後來查詢多方說法後(StackOverFlow網友建議),建議這種射後不理的整合寫法,可以採用TPL(工作型非同步執行庫)
正規TPL的非同步方法在Handle的時候如下:
其例外處理範例,因為Task的例外會拋出來的是AggregateException方法。因此可以例用以下方法來走訪所有的Exception
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
try
{
task1.Wait();
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw;
}
}
}
}
後續改寫一版後,能明確抓到射後不理的Exception,也不會造成集區崩潰就變成以下的版本了
Task listenerTask = Task.Run(() => proxy.callService<ResultObject>(inputObj)).ContinueWith(
t => { logException(t, proxy.ServiceName); }, TaskContinuationOptions.OnlyOnFaulted);
private static void logException(Task<BaseAddOutput> t, string serviceName)
{
var message = string.Empty;
if (t.Exception != null)
message = t.Exception.Message;
if (t.Exception.InnerException != null)
message = t.Exception.InnerException.Message;
Debug.Log(ConfigUtil.GetBoolean("Debug"), "system call " + serviceName + " error, msg:" + message);
}
當然,若不是要射後不理的話,建議還是要讓function async / wait化,來確保執行流程順序中的工作都有被完成
MS Docs參考
https://docs.microsoft.com/zh-tw/dotnet/standard/parallel-programming/task-based-asynchronous-programming