将异步方法传递给Parallel.ForEach [英] Passing async method into Parallel.ForEach
问题描述
我正在阅读有关Parallel.ForEach
的这篇文章,其中"Parallel.ForEach与传入异步方法不兼容."
I was reading this post about Parallel.ForEach
where it was stated that "Parallel.ForEach is not compatible with passing in a async method."
因此,要检查一下我是否编写了这段代码:
So, to check I write this code:
static async Task Main(string[] args)
{
var results = new ConcurrentDictionary<string, int>();
Parallel.ForEach(Enumerable.Range(0, 100), async index =>
{
var res = await DoAsyncJob(index);
results.TryAdd(index.ToString(), res);
});
Console.ReadLine();
}
static async Task<int> DoAsyncJob(int i)
{
Thread.Sleep(100);
return await Task.FromResult(i * 10);
}
此代码同时填写results
词典.
This code fills in the results
dictionary concurrently.
顺便说一句,我创建了一个类型为ConcurrentDictionary<string, int>
的字典,因为如果在调试模式下浏览其元素时遇到ConcurrentDictionary<int, int>
的情况,我会发现该元素是按键排序的,因此我认为添加了优雅元素.
By the way, I created a dictionary of type ConcurrentDictionary<string, int>
because in case I have ConcurrentDictionary<int, int>
when I explore its elements in debug mode I see that elements are sorted by the key and I thought that elenents was added consequently.
所以,我想知道我的代码是否有效?如果它与传递异步方法不兼容",为什么它运行良好?
So, I want to know is my code is valid? If it "is not compatible with passing in a async method" why it works well?
推荐答案
此代码仅适用于DoAsyncJob
并不是真正的异步方法. async
不会使方法异步工作.等待已完成的任务(如Task.FromResult
返回的任务)也是同步的. async Task Main
不包含任何异步代码,这会导致编译器警告.
This code works only because DoAsyncJob
isn't really an asynchronous method. async
doesn't make a method work asynchronously. Awaiting a completed task like that returned by Task.FromResult
is synchronous too. async Task Main
doesn't contain any asynchronous code, which results in a compiler warning.
一个演示Parallel.ForEach
如何不适用于异步方法的示例应调用一个真正的异步方法:
An example that demonstrates how Parallel.ForEach
doesn't work with asynchronous methods should call a real asynchronous method:
static async Task Main(string[] args)
{
var results = new ConcurrentDictionary<string, int>();
Parallel.ForEach(Enumerable.Range(0, 100), async index =>
{
var res = await DoAsyncJob(index);
results.TryAdd(index.ToString(), res);
});
Console.WriteLine($"Items in dictionary {results.Count}");
}
static async Task<int> DoAsyncJob(int i)
{
await Task.Delay(100);
return i * 10;
}
结果将是
Items in dictionary 0
Parallel.ForEach 没有接受Func<Task>
的重载,它仅接受Action
委托.这意味着它无法等待任何异步操作.
Parallel.ForEach has no overload accepting a Func<Task>
, it accepts only Action
delegates. This means it can't await any asynchronous operations.
async index
是因为它隐式地是 async void
代表.就Parallel.ForEach
而言,它只是一个Action<int>
.
async index
is accepted because it's implicitly an async void
delegate. As far as Parallel.ForEach
is concerned, it's just an Action<int>
.
结果是Parallel.ForEach
触发了100个任务,并且从不等待它们完成.这就是为什么在应用程序终止时字典仍然为空的原因.
The result is that Parallel.ForEach
fires off 100 tasks and never waits for them to complete. That's why the dictionary is still empty when the application terminates.
这篇关于将异步方法传递给Parallel.ForEach的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!