2015-10-06 108 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具有所有必要的異步方法。 –