异步foreach

alo*_*gah 9 c# foreach asynchronous

有没有办法在C#中使用异步foreach?其中id(s)将由方法异步处理,而不是使用Parallel.ForEach

//This Gets all the ID(s)-IEnumerable <int>
var clientIds = new Clients().GetAllClientIds(); 

Parallel.ForEach(clientIds, ProcessId); //runs the method in parallel

static void ProcessId(int id)
{
// just process the id  
}
Run Code Online (Sandbox Code Playgroud)

应该是一个foreach,但异步运行

foreach(var id in clientIds)
{
   ProcessId(id) //runs the method with each Id asynchronously??
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试在控制台中运行程序,它应该在关闭控制台之前等待所有ID完成处理.

Paw*_*oka 18

不,这不可能.

而不是在foreach循环中添加您想要执行的任务作为任务集合以及稍后使用Task.WaitAll.

var tasks = new List<Task>();

foreach(var something in somethings)
 tasks.Add(DoJobAsync(something));

await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)

请注意,方法DoJobAsync应返回Task.

更新:

如果你的方法没有返回Task而是返回其他东西(例如void)你有两个基本相同的选项:

1.将Task.Run(action)添加到任务集合中

tasks.Add(Task.Run(() => DoJob(something)));
Run Code Online (Sandbox Code Playgroud)

2.在返回Task的方法中包装sync方法

 private Task DoJobAsync(Something something)
 {
     return Task.Run(() => DoJob(something));
 }
Run Code Online (Sandbox Code Playgroud)

Task<TResult>如果要从任务执行中获得一些结果,也可以使用泛型.


Nko*_*osi 7

您的目标方法必须返回一个任务

static Task ProcessId(int id)
{
    // just process the id  
}
Run Code Online (Sandbox Code Playgroud)

处理ID将像这样完成

// This Gets all the ID(s)-IEnumerable <int>
var clientIds = new Clients().GetAllClientIds(); 
// This gets all the tasks to be executed
var tasks = clientIds.Select(id => ProcessId(id)).
// this will create a task that will complete when all of the `Task` 
// objects in an enumerable collection have completed. 
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)