我有案例我想在paralle.Foreach循环中调用一个asyn方法
public void ItemCheck<T>(IList<T> items,int id)
{
Parallel.ForEach(items, (current) =>
{
PostData(current,id);
});
Console.log("ItemCheck executed")
}
public async void PostData<T>(T obj, int id)
{
Console.lgo("PosstData executed")
}
输出:
ItemCheck executed
PosstData executed
为什么会这样? 在完成PostData 方法的执行之前,执行下一行。如何解决此问题。任何人都可以帮助
答案 0 :(得分:3)
为什么会这样?
因为您使用的是async void
。
另外 - 正如Jon Skeet所说 - 在这里做并行是没有意义的。并行处理是将工作分成多个线程。你真正想要的是并发,而不是 parallelism ,这可以用Task.WhenAll
完成:
public async Task ItemCheckAsync<T>(IList<T> items, int id)
{
var tasks = items.Select(current => PostDataAsync(current, id));
await Task.WhenAll(tasks);
}
public async Task PostDataAsync<T>(T obj, int id)
短语“并行”通常用于表示“一次执行多项操作”,但该用法误导您使用Parallel
,在这种情况下,这不是合适的工具。这就是为什么我强烈喜欢术语“并发”的一个原因,并为Parallel
类所做的事情保留术语“并行”。
答案 1 :(得分:0)
问题是你的PostData
方法是异步执行的,没有任何东西告诉并行循环要等到所有任务完成。
我将使用另一种方法来同步执行流程:
var tasks = items
.AsParallel()
.WithDegreeOfParallelisum(...)
.Select(async item => await PostData(item, id))
.ToArray();
Task.WaitAll(tasks); // this will wait for all tasks to finnish
也是你的异步方法,即使是空的,它们应该返回Task
而不是无效。更明确地了解您的代码是这种方法的一个优点,此外,您可以将任务用于任何其他操作,例如等待完成的情况。
public async Task PostData<T>(T obj, int id)
您是否需要并行创建/启动异步任务然后等待它们?这样做的结果就是并行创建任务(这不是一个繁重的操作,为什么要并行执行?)。
如果除了PostData
方法之外你没有在并行循环中做任何额外繁重的工作,我认为你根本不需要并行循环。