我经常应用中的顶级功能的工作原理常见的类似任务异步模式和错误/异常/注销处理
public Result5 ProcessAll() {
var result1 = Process1();
var result2 = Process2();
var result3 = Process3(result1);
var result4 = Process4(result1, result2);
return Process5(result1, result2, result3, result4);
}
的进程*功能:
- IO绑定(数据库,文件系统,web服务)
- 可能会抛出异常,只是在调用栈中传播
- 可能会返回错误的一些非例外呃rors应该停止处理并返回
顶级函数也在后台线程上运行,可以取消。 这意味着全面落实看起来像
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);
}
现在我需要把取消检查:-)
我现在的问题是:
所有这些检查早期任务中的失败,错误和取消都变得容易出错,并且不具有可扩展性。 我在这里错过了一些重要的东西,并以错误的方式去做?
你有没有试过这些链接 - 这个领域已经很好地覆盖了,但不知道它是否完全适用于你有什么 - http://nitoprograms.blogspot.com/2010/06/reporting-progress-from-tasks。 HTML - 和http://nitoprograms.blogspot.com/2012/02/reporting-progress-from-async-tasks.html - 我想你应该看看,如果还没有。 – NSGaga 2012-04-08 15:44:46
我假设你不能使用C#5,对吧? – svick 2012-04-08 19:33:20
@svick .Net 3.5和4只。是否等待简化并行操作?我的理解是,等待主要是关于异步工作(即在这种情况下实现Process *方法)。你有一个例子吗? – adrianm 2012-04-09 06:24:53