2015-10-06 62 views
0

考虑一个场景,我们必须调用一个方法,依次调用数据库foreach中的对象列表。使Foreach异步

List<object> Response= new List<object> 
foreach(object obj in List<object>) 
{ 
    Resposne.add(callMethod()); 
} 

如何运行这个foreach循环异步,我想打电话给列表中的下一个对象callmethod无需等待第一个对象调用返回。一旦所有的呼叫都成功返回,控制权应该返回给客户端。

由于callMethod函数正在调用数据库,所以顺序执行需要时间。为了提高性能,我需要运行这个异步。

+4

喜欢的东西[' Parallel.ForEach'](https://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx) ? – npinti

+1

我希望代码只是一个不好的例子,因为它不会做那样的事情。 – poke

回答

2

我想为列表中的下一个对象调用callmethod而不用等待第一个对象调用返回。

你真的想parallelize your loop

List<object> Response= new List<object>(); 
// You need to put some stuff on Response 
Parallel.ForEach(Response, o => 
{ 
    Response.Add(callMethod()); 
}); 
+0

虽然您的解决方案的想法是正确的,但我强烈建议在将项目添加到共享列表对象之前使用锁定。或者,也可以使用不同版本的使用线程/分区局部变量的Parallel.ForEach循环。作为一个小提示:它应该是'Parallel.ForEach(someVariableName,...' – Dirk

+0

我在CallMethod()中调用外部数据库,我认为parllel不会提高性能 –

+0

不要使用'Parallel.Foreach对于IO操作,它将继续创建新的线程,而现有的则等待IO结束。 –

1

callMethod()是一个IO操作,所以不要使用`Parallel.Foreach”。

Parallel.Foreach是专为并行计算。当你想执行并行CPU密集型操作时,它可以很好地扩展。但是,如果调用同步IO操作,线程将被阻塞,等待操作完成。这是浪费资源,因为线程在阻塞时不能被重用。更糟糕的是,调度器将继续为`Parallel.Foreach'创建新线程来保持CPU繁忙。它在客户端应用程序中可能不是一个很大的问题,但在具有许多并发请求的服务器应用程序中,它将是一个瓶颈。

你应该让你的callMethod()异步

private async Task<int> callMethodAsync() 

在该方法使一个异步操作,例如

using (SqlDataReader reader = await command.ExecuteReaderAsync()) 

然后使用它是这样的:

int[] results = await Task.WhenAll(from obj in list select callMethodAsync()); 
+0

问题是我正在使用postgres,而我的datareader不是异步的。 –

+0

@manthandavda你用什么来连接数据库? Npgsql具有所有必要的异步方法。 –