C# Parallel.ForEach的终结器
如何添加在所有并行完成后运行的终结器C# Parallel.ForEach的终结器,c#,.net,multithreading,C#,.net,Multithreading,如何添加在所有并行完成后运行的终结器 Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, async (entry) => // Do something with the entry. }); 我试过这样做,但没有编译: Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }
Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, async (entry) =>
// Do something with the entry.
});
我试过这样做,但没有编译:
Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, async (entry) =>
// Do something with the entry.
}, () => { // Was hoping this would work. });
你什么都不用做。您的
Parallel.ForEach
将一直运行,直到所有线程完成其工作。这是Parallel.Foreach()
的一个非常好的优点
所以就在
Parallel.ForEach(()=>{/*code*/})之后代码>所有线程都将完成。您无需执行任何操作。您的Parallel.ForEach
将一直运行,直到所有线程完成其工作。这是Parallel.Foreach()
的一个非常好的优点
所以就在Parallel.ForEach(()=>{/*code*/})之后代码>所有线程都将完成
您应该而不是将Parallel.ForEach
的操作声明为async
。如果在该操作中使用wait
,则控制流将返回到Parallel.ForEach
,其实现“认为”该操作已完成。这将导致与您预期的行为截然不同的行为
循环完成后,Parallel.ForEach
的调用返回。对枚举中的所有元素执行所有操作后返回。因此,“当所有并行完成”后,您想做的任何事情都可以在调用之后立即完成:
Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 },
(entry) =>
// Do something with the entry.
);
DoSomethingWhenAllParallelsHaveCompleted();
您应该而不是将Parallel.ForEach
的操作声明为async
。如果在该操作中使用wait
,则控制流将返回到Parallel.ForEach
,其实现“认为”该操作已完成。这将导致与您预期的行为截然不同的行为
循环完成后,Parallel.ForEach
的调用返回。对枚举中的所有元素执行所有操作后返回。因此,“当所有并行完成”后,您想做的任何事情都可以在调用之后立即完成:
Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 },
(entry) =>
// Do something with the entry.
);
DoSomethingWhenAllParallelsHaveCompleted();
正如我和其他人在注释Parallel.ForEach
中提到的那样,它不支持异步函数,原因是当您执行async(entry)=>…
时,它与
Parallel.ForEach(entries, Example);
//elsewhere
async void Example(Entry entry)
{
...
}
由于函数是async void
,ForEach
无法判断函数何时“完成”,因此当您点击第一个wait
而不是任务完成时,它会认为函数已完成
解决这个问题的方法是使用一个支持异步函数的库,这是一个很好的方法。您可以通过将NuGet包安装到项目中来获得它。您可以将以前的代码重新创建为
private const int MAX_PARALLELISM = 15
public async Task ProcessEntries(IEnumerable<Entry> entries)
{
var block = new ActionBlock<Entry>(async (entry) =>
{
//This is now a "async Task" instead of a async void
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = MAX_PARALLELISM
});
foreach(var entry in entries)
{
await block.SendAsync(entry);
}
block.Complete();
await block.Completion;
DoExtraWorkWhenDone();
}
private const int MAX_PARALLELISM=15
公共异步任务ProcessEntries(IEnumerable条目)
{
变量块=新操作块(异步(条目)=>
{
//这现在是一个“异步任务”,而不是异步任务
},
新的ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism=最大并行度
});
foreach(分录中的var分录)
{
wait block.SendAsync(条目);
}
block.Complete();
等待区块完成;
DoExtraWorkWhenDone();
}
正如我和其他人在评论Parallel中提到的那样。ForEach
不支持异步函数,原因是当您执行异步(条目)=>…
时,与
Parallel.ForEach(entries, Example);
//elsewhere
async void Example(Entry entry)
{
...
}
由于函数是async void
,ForEach
无法判断函数何时“完成”,因此当您点击第一个wait
而不是任务完成时,它会认为函数已完成
解决这个问题的方法是使用一个支持异步函数的库,这是一个很好的方法。您可以通过将NuGet包安装到项目中来获得它。您可以将以前的代码重新创建为
private const int MAX_PARALLELISM = 15
public async Task ProcessEntries(IEnumerable<Entry> entries)
{
var block = new ActionBlock<Entry>(async (entry) =>
{
//This is now a "async Task" instead of a async void
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = MAX_PARALLELISM
});
foreach(var entry in entries)
{
await block.SendAsync(entry);
}
block.Complete();
await block.Completion;
DoExtraWorkWhenDone();
}
private const int MAX_PARALLELISM=15
公共异步任务ProcessEntries(IEnumerable条目)
{
变量块=新操作块(异步(条目)=>
{
//这现在是一个“异步任务”,而不是异步任务
},
新的ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism=最大并行度
});
foreach(分录中的var分录)
{
wait block.SendAsync(条目);
}
block.Complete();
等待区块完成;
DoExtraWorkWhenDone();
}
Parallel.ForEach无法正常工作当您执行async(entry)=>
时,请不要对其使用异步方法。您必须使用非异步方法或切换到类似的东西。并行。ForEach
对于返回任务的函数没有重载,因此您的异步函数将立即返回,迭代将立即完成。请参阅.Parallel.ForEach在执行async(entry)=>
时无法正常工作,请不要对其使用异步方法。您必须使用非异步方法或切换到类似的东西。并行。ForEach
对于返回任务的函数没有重载,因此您的异步函数将立即返回,迭代将立即完成。看,那我怎么在行动中等待呢?我需要使用一个HttpClient
来发送数据,它上面有一个SendAsync
方法。@Alexandru您需要使用.Wait()
或.Result
。你能举个例子吗.Result
可能会死锁,我不确定.Wait()
是否能保证结果