我有一个典型的foreach循环,它调用一个方法,其中参数是我们循环的集合的一个元素;像这样的东西:
foreach (byte x in SomeCollection)
{
SomeMethod(x);
}
问题是SomeMethod
需要很长时间才能运行。我想将调用移动到一个新任务,以便循环只创建任务,然后调用循环的线程继续。我如何以线程安全的方式执行此操作?
感谢。
修改
我遇到了性能问题,因为SomeMethod
进行了几次数据库调用。所以我将循环转换为Parallel.ForEach
,但这并没有太大的区别,因为每个线程然后调用数据库。我要做的只是创建在后台运行的任务,让主线程继续。
答案 0 :(得分:11)
一种方法是使用Parallel.ForEach
来执行此操作:
Parallel.ForEach(SomeCollection, x => SomeMethod(x));
代码将在继续之前等待SomeMethod
的所有调用完成,但各个调用可以并行运行。
如果您不想等待通话结束,请将此通话包裹在StartNew
中:
Task.Factory.StartNew(() => Parallel.ForEach(SomeCollection, x => SomeMethod(x)));
答案 1 :(得分:1)
您期望什么线程安全?这将是线程安全的:
foreach (byte x in SomeCollection) { Task.Factory.StartNew(() => SomeMethod(x)); }
直到你的方法不修改任何共享状态,这本身并不是线程安全的。
答案 2 :(得分:1)
你可以这样:
IEnumerable<Task> doWork()
{
foreach(var x in SomeCollection)
yield return Task.Run(()=>SomeMethod(x);
}
Task.WhenAll(doWork());
这将同时运行它们。