Jer*_*xon 2 c# parallel-processing multithreading
在过去我做过这样的事情:
List<Item> _Items = GetItems();
int _CountDown = _Items.Count;
using (BackgroundWorker _Worker = new BackgroundWorker())
{
_Worker.DoWork += (s, arg) =>
{
DoSomething(_Items[_CountDown]);
};
_Worker.RunWorkerCompleted += (s, arg) =>
{
if (System.Threading.Interlocked.Decrement(ref _CountDown) == 0)
RaiseAllDoneEvent();
else
_Worker.RunWorkerAsync();
};
_Worker.RunWorkerAsync();
}
Run Code Online (Sandbox Code Playgroud)
和平行我做这样的事情:
List<Item> _Items = GetItems();
int _CountDown = _Items.Count;
System.Threading.Tasks.Parallel.ForEach(_Items, (i) =>
{
DoSomething(i);
if (System.Threading.Interlocked.Decrement(ref _CountDown) == 0)
RaiseAllDoneEvent();
});
Run Code Online (Sandbox Code Playgroud)
我真正的问题是:Interlocked.Decrement()在这里是否正确?
Parallel.ForEach将阻塞直到所有项都被处理 - 这里正确的做法似乎是在调用Parallel.ForEach之后立即从调用者调用RaiseAllDoneEvent():
List<Item> _Items = GetItems();
System.Threading.Tasks.Parallel.ForEach(_Items, (i) =>
{
DoSomething(i);
});
RaiseAllDoneEvent();
Run Code Online (Sandbox Code Playgroud)
换句话说,根本不需要倒计时(或跟踪要处理的项目数).如果您希望并行操作不阻止,可以将其转换为一堆任务:
List<Item> _Items = GetItems();
Task.Factory.StartNew(()=> {
Task.WaitAll(
_Items.Select(i => Task.Factory.StartNew(() => DoSomething(i))).ToArray()
);
}).ContinueWith(t => RaiseAllDoneEvent());
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你将开始一个外部任务来旋转,然后等待一堆任务(每个项目一个),然后最终提升所有完成的事件.这些都不会阻止原始呼叫者.