在foreach循环中创建任务

本文关键字:创建 任务 循环 foreach | 更新日期: 2023-09-27 18:16:26

我有一个典型的foreach循环,它调用一个方法,其中参数是我们正在循环的集合的元素;像这样:

foreach (byte x in SomeCollection)
{
   SomeMethod(x);
}

问题是SomeMethod需要很长时间才能运行。我想把调用移动到一个新任务中,这样循环就会创建任务,然后调用循环的线程就会继续。我如何以线程安全的方式做到这一点?

编辑

我有一个性能问题,因为SomeMethod进行了几个DB调用。所以我将循环转换为Parallel.ForEach,但这并没有太大的区别,因为每个线程然后调用DB。我要做的就是创建任务,将运行在后台,让主线程继续。

在foreach循环中创建任务

一种方法是使用Parallel.ForEach来做到这一点:

Parallel.ForEach(SomeCollection, x => SomeMethod(x));

代码将等待SomeMethod的所有调用完成后再继续,但是单个调用可以并行运行。

如果您不想等待调用完成,请将此调用封装在StartNew:

Task.Factory.StartNew(() => Parallel.ForEach(SomeCollection, x => SomeMethod(x)));

你期望什么样的线程安全?这将是线程安全的:

foreach (byte x in SomeCollection) { Task.Factory.StartNew(() => SomeMethod(x)); }
直到你的方法不修改任何共享状态,否则它本身就不是线程安全的。

你可以这样写:

IEnumerable<Task> doWork()
{
  foreach(var x in SomeCollection)
    yield return Task.Run(()=>SomeMethod(x);
}
Task.WhenAll(doWork());

这将同时运行它们