我有一个序列的任务,其中的每一个取决于previous 1的输出。我想重新present这是一个工作
对象,其结果是该序列的末端的输出。 (如果任务不依赖于彼此,然后我能做到这一点的同时,我会使用 TaskFactory.ContinueWhenAll
)
I have a sequence of tasks, where each one depends on the output of the previous one. I'd like to represent this as a single Task
object, whose result is the output of the end of the sequence. (If the tasks didn't depend on one another then I could do it in parallel and I would use TaskFactory.ContinueWhenAll
.)
我希望能够实现这个方法:
I'd like to be able to implement this method:
static Task<TState> AggregateAsync<T, TState>(
IEnumerable<T> items,
TState initial,
Func<TState, T, Task<TState>> makeTask);
如何有效地运行的任务一个接一个顺序?我使用C#4.0,所以我不能用异步
/ 等待
来为我做的。
How can I efficiently run the tasks one after another in sequence? I'm using C# 4.0 so I can't use async
/await
to do it for me.
编辑:我可以写 AggregateAsync
是这样的:
static Task<TState> AggregateAsync<T, TState>(IEnumerable<T> items, TState initial, Func<TState, T, Task<TState>> makeTask)
{
var initialTask = Task.Factory.StartNew(() => initial);
return items.Aggregate(
initialTask,
(prevTask, item) =>
{
prevTask.Wait(); // synchronous blocking here?
return makeTask(prevTask.Result, item);
});
}
但可以肯定,我会收到得到一批任务,其中每一个块同步等待一个?
But surely I'll get a batch of tasks, each of which blocks synchronously waiting for the one before it?
最简单的方式(使用 Microsoft.Bcl.Async
):
The easy way (using Microsoft.Bcl.Async
):
static async Task<TState> AggregateAsync<T, TState>(
this IEnumerable<T> items,
TState initial,
Func<TState, T, Task<TState>> makeTask)
{
var state = initial;
foreach (var item in items)
state = await makeTask(state, item);
return state;
}
硬的方式:
static Task<TState> AggregateAsync<T, TState>(
this IEnumerable<T> items,
TState initial,
Func<TState, T, Task<TState>> makeTask)
{
var tcs = new TaskCompletionSource<TState>();
tcs.SetResult(initial);
Task<TState> ret = tcs.Task;
foreach (var item in items)
{
var localItem = item;
ret = ret.ContinueWith(t => makeTask(t.Result, localItem)).Unwrap();
}
return ret;
}
请注意,错误处理是比较尴尬的硬的方式;从第一个项目的异常将被包装在一个 AggregateException
由每个连续的项目。 易的方法不换行的例外是这样的。
Note that error handling is more awkward with the "hard" way; an exception from the first item will be wrapped in an AggregateException
by each successive item. The "easy" way does not wrap exceptions like this.