2016-12-13 54 views
-2

我想我PLINQ聲明這樣的組合:與異步方法結合PLINQ

Enumerable.Range(0, _sortedList.Count()).AsParallel().WithDegreeOfParallelism(10) 
      .Select(i => GetTransactionDetails(_sortedList[i].TransactionID)) 
      .ToList(); 

採用異步方法是這樣的:

private async void GetTransactionDetails(string _trID) 
{ 
     await Task.Run(() => 
     { 
     }); 
} 

所以,我可以簡單地添加一個的await操作在這裏:

Enumerable.Range(0, _sortedList.Count()).AsParallel().WithDegreeOfParallelism(10) 
      .Select(i => await GetTransactionDetails(_sortedList[i].TransactionID)) 
      .ToList(); 

我該如何做到這一點?

P.S.通過這種方式,我可以同時發出5-10個HTTP請求,同時確保最終用戶在這樣做時不會感覺到任何「屏幕」凍結...

+0

爲什麼你想並行化異步操作的*開始*,因爲開始它基本上不需要任何時間。 PLINQ用於長時間運行CPU綁定操作;這不是你所擁有的。另外,它看起來像'GetTransactionDetails'正在使用異步同步反模式。它不應該將工作轉移到另一個線程,而應該是一個同步方法。如果調用者想用'Task.Run'調用它,他們可以,如果他們想要做別的事情,比如使用PLINQ,那麼他們可以做到這一點。 – Servy

+0

@Servy你能告訴我怎麼才能實現你剛剛在一個更實際的例子中所說的話嗎? – User987

+0

從'GetTransactionDetails'中刪除'Task.Run',並讓它同步完成工作,從而允許PLINQ對其進行並行化。 – Servy

回答

2

您可以採取幾種方法。

首先,「更正確」的方法(這也是更多的工作)。讓GetTransactionDetails成適當async方法(即不使用Task.Run):

private async Task GetTransactionDetailsAsync(string _trID); 

然後你就可以同時調用該方法:

var tasks = _sortedList.Select(x => GetTransactionDetailsAsync(x.TransactionID)); 
await Task.WhenAll(tasks); 

如果您需要限制併發,使用SemaphoreSlim

第二種方法比較浪費(在線程使用方面),但考慮到我們已經看到代碼的哪些部分,可能會更容易。第二種方法是離開I/O的所有同步,只是做一個常規PLINQ時尚:

private void GetTransactionDetails(string _trID); 

_sortedList.AsParallel().WithDegreeOfParallelism(10).Select(x => GetTransactionDetails(x.TransactionID)).ToList(); 

爲了避免阻塞UI線程,你可以在一個Task.Run把這個包:

await Task.Run(() => _sortedList.AsParallel().WithDegreeOfParallelism(10).Select(x => GetTransactionDetails(x.TransactionID)).ToList()); 
+0

非常驚人的回覆,謝謝! await Task.Run()正是我在這種情況下所需要的...雖然我必須使用Parallel.For與Parallel.For循環的組合,而不是您在示例中顯示的那個,因爲.Select方法不會'用void方法工作,至少這是編譯器給我看的東西? – User987

+0

我有CPU綁定的異步方法,它只執行一小部分IO,但需要並行處理CPU綁定的東西。它使用的接口沒有同步API。我做的是'Task.WhenAll(items.Select(item => Task.Run(async()=> {/ *方法等待* /})))'。 Task.Run將處理在第一次等待之前發生的CPU綁定工作。一次排隊到線程池似乎是目前爲止最快的。 – jnm2

+0

無論如何,我認爲永遠不會浪費IO上的線程。 – jnm2