[英]Task Asynchronous Pattern and error/exception/cancellation handling
我經常有頂級 function 工作的應用程序
public Result5 ProcessAll() {
var result1 = Process1();
var result2 = Process2();
var result3 = Process3(result1);
var result4 = Process4(result1, result2);
return Process5(result1, result2, result3, result4);
}
Process* 函數的共同點是:
頂級 function 也在可以取消的后台線程上運行。 這意味着完整的實現看起來像
public Result5 ProcessAll(CancellationToken cancellationToken) {
Result1 result1 = Process1();
if (result1 == null)
return null;
cancellationToken.ThrowIfCancellationRequested();
Result2 result2 = Process2();
if (result2 == null)
return null;
cancellationToken.ThrowIfCancellationRequested();
Result3 result3 = Process3(result1);
if (result3 == null)
return null;
cancellationToken.ThrowIfCancellationRequested();
Result4 result4 = Process4(result1, result2);
if (result4 == null)
return null;
cancellationToken.ThrowIfCancellationRequested();
return Process5(result1, result2, result3, result4);
}
現在假設我需要通過盡可能多地並行運行來加快速度。
還假設 Process* 函數實現任務異步模式並使用 IO 完成端口或類似端口。
我一直沒能為此找到任何好的模式。
如果我忽略錯誤/異常/取消,它將看起來像這樣。
public Result5 ProcessAll(CancellationToken cancellationToken) {
Task<Result1> task1 = Process1Async();
Task<Result2> task2 = Process2Async();
Task<Result3> task3 = task1.ContinueWith(_ => Process3Async(task1.Result)).Unwrap();
Task<Result4> task4 = Task.Factory.ContinueWhenAll(new[] { task1, task2 },
_ => Process4Async(task1.Result, task2.Result)).Unwrap();
// This will trigger all exceptions captured
Task.WaitAll(new[] { task1, task2, task3, task4 });
return Process5(task1.Result, task2.Result, task3.Result, task4.Result);
}
(我知道這可以像同步運行 task4 一樣進行優化,並且 WaitAll 不是必需的,但我只是在這里展示一種模式)
如果我現在嘗試處理錯誤和異常,它可能看起來像這樣:
public Result ProcessAll(CancellationToken cancellationToken) {
Task<Result1> task1 = Process1Async();
Task<Result2> task2 = Process2Async();
// Process 3 should not run if task1 or task2 failed or returned error
Task<Result3> task3 = task1.ContinueWith(_ => {
if (task1.IsFaulted || task1.Result == null)
return null;
if (task2.IsFaulted || (task2.IsCompleted && task2.Result == null)
return null;
return Process3Async(task1.Result);
}).Unwrap();
// Process4 should not start if any of Process1,Process2 or Process3 returned error or throw exception
Task<Result4> task4 = Task.Factory.ContinueWhenAll(new[] { task1, task2 }, _ => {
if (task1.Faulted || task1.Result == null)
return null;
if (task2.Faulted || task2.Result == null)
return null;
if (task3.Faulted || (task3.IsCompleted && task3.Result == null))
return null;
return Process4Async(task1.Result, task2.Result)).Unwrap();
Task.WaitAll(new[] { task1, task2, task3, task4 });
if (task1.Result == null ||
task2.Result == null ||
task3.Result == null ||
task4.Result == null)
return null;
return Process5(task1.Result, task2.Result, task3.Result, task4.Result);
}
現在我需要進行取消檢查:-)
我現在的問題是:
所有這些對早期任務中的失敗、錯誤和取消的檢查都變得容易出錯並且可擴展性不強。 我在這里錯過了一些重要的東西並且以錯誤的方式做嗎?
我只能在所有較早的進程都完成后才能啟動進程 3、4 和 5,無論如何它們都沒有並行性。 所以你不需要為他們使用任務。 您只需要為前兩個任務使用任務,這樣問題就容易多了。 如果您選擇將它們作為任務啟動,這些任務將始終等待前任,從而消除任何並行性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.