Uri*_*Uri 3 c# multithreading thread-safety task-parallel-library parallel.foreach
我有这段代码:
int totalData = result.Data.Count;
int count = 0;
Parallel.ForEach(result.Data, data =>
{
try
{
EventRange importedEntity = ImportEntity(auxResult.EntityName, data);
count++;
EntityImported(importedEntity, count, totalData);
}
catch (Exception e)
{
exceptions.Enqueue(e);
}
});
Run Code Online (Sandbox Code Playgroud)
EntityImported是一个事件,应该说已经处理了多少实体,以及我应该处理多少实体.我担心的是增加lambda内部计数的线程安全性,以及您建议采用哪些步骤来确保始终使用count变量的正确值触发事件.
目前它根本不是线程安全的.
你可以使用Interlocked.Increment(ref count),但通常最好为每个线程都有一个"本地"值,并在最后加上它们.这样,除了分配要处理的项目之外,您不需要任何类型的跨线程数据流.
Parallel.ForEach设计用于此目的的重载- 查看文档底部附近的示例,因为它正在执行与您的代码非常相似的操作.(它维护一个本地计数,然后在最后对计数求和.)不幸的是,由于您需要在每次迭代时引发事件的方式,这对您的特定情况没有帮助 - 但通常这是一种更好的方法.
在这种情况下,您应该Interlocked.Increment在事件提升代码中使用结果:
Parallel.ForEach(result.Data, data =>
{
try
{
EventRange importedEntity = ImportEntity(auxResult.EntityName, data);
int newCount = Interlocked.Increment(ref count);
EntityImported(importedEntity, newCount, totalData);
}
catch (Exception e)
{
exceptions.Enqueue(e);
}
});
Run Code Online (Sandbox Code Playgroud)
这样,每个计数都会引发一个事件(因此一个为0,一个为1,一个为2等).