我有一个静态通用方法,旨在并行执行对集合的操作(不用担心限制;我已经覆盖了这些;这里的代码是愚蠢的 - 下载版本):
public static IEnumerable<Task> RunAllAsync<T>(this IEnumerable<T> enumerable, Action<T> action)
{
var tasks = new List<Task>();
foreach (var t in enumerable)
{
tasks.Add(Task.Run(() => action(t)));
}
return tasks;
}
以下是使用方法的示例:
public async Task UsageSync()
{
var numbers = Enumerable.Range(1, 5);
var random = new Random();
var tasks = numbers.RunAllAsync(i =>
{
Console.WriteLine($"A {i}");
Thread.Sleep(random.Next(1000));
Console.WriteLine($"B {i}");
});
Console.WriteLine("Awaiting end");
await Task.WhenAll(tasks.ToArray());
Console.WriteLine("awaited");
Thread.Sleep(2000);
Console.WriteLine("Finished");
}
输出:
Awaiting end
A 4
A 5
A 1
A 2
A 3
B 3
B 2
B 1
B 5
B 4
awaited
Finished
一切如预期。但现在我们将该操作本身设为异步代理:
public async Task UsageAsync()
{
var numbers = Enumerable.Range(1, 5);
var random = new Random();
var tasks = numbers.RunAllAsync(async i =>
{
Console.WriteLine($"A {i}");
await Task.Run(() =>
{
Console.WriteLine($"B {i}");
Thread.Sleep(random.Next(1000));
Console.WriteLine($"C {i}");
});
});
Console.WriteLine("Awaiting end");
await Task.WhenAll(tasks.ToArray());
Console.WriteLine("awaited");
Thread.Sleep(2000);
Console.WriteLine("Finished");
}
输出:
Awaiting end
A 4
B 4
A 1
A 5
A 3
A 2
B 2
awaited
B 5
B 1
B 3
C 3
C 2
C 1
C 5
C 4
Finished
看到了吗?达到等待的方法&#34;在线程结束之前!
我应该做些什么来确保等待异步操作?
答案 0 :(得分:4)
由于您正在处理Action<T>
,async i => { ... }
会被转换为async void
方法。设计async void
使得无法等待它完成。将您的参数更改为Func<T, Task> func
,并将通话action(t)
更改为await func(t)
。