2015-05-15 17 views
1

我有一個異步方法,它應該查找數據庫條目。它按名稱進行過濾,因此是並行執行的候選者。如何等待LINQ的ParallelQuery?

但是,我找不到一個簡單的方法來支持並行執行和異步任務。

這是我有:

private async Task<List<Item>> GetMatchingItems(string name) { 
    using (var entities = new Entities()) { 
     var items = from item in entities.Item.AsParallel() 
       where item.Name.Contains(name) 
       select item; 
     return await items.ToListAsync(); //complains "ParallelQuery<Item> does not contain a definition for ToListAsync..." 
    } 
} 

當我刪除AsParallel()它會編譯。我不應該同時使用這兩個功能?或者我理解錯了什麼?

IHMO,都有道理:

  • AsParallel(),就表示這個數據庫查詢可以得到分成,同時運行幾個子查詢,因爲任何一項的個別匹配不依賴於任何其他項目。 更新:在這個例子中的壞主意,請參閱評論和答案!
  • ToListAsync()將支持此方法的異步執行,以允許其他匹配方法(在其他數據上)立即開始執行。

如何同時使用並行exectuion(與LINQ)和異步任務?

+3

爲什麼你想在數據庫查詢中使用'.AsParallel()'?你認爲它速度更快嗎?它會崩潰得更快,如果這是你想要的...請去閱讀斯蒂芬克萊裏的博客... – Aron

+0

我想你的意思是這一個:http://blog.stephencleary。com/2014/04/a-tour-of-task-part-0-overview.html – Marcel

+1

問題是您試圖讓EF使用平行度優化您的查詢。這是SQL服務器查詢計劃生成器的工作。在這種情況下將查詢拆分實際上具有負面影響。 – Aron

回答

3

你不能,也不應該。 PLINQ不適用於數據庫訪問。數據庫最瞭解如何對查詢進行並行化,並使用普通的LINQ來完成自己的工作。 PLINQ用於訪問對象,在LINQ查詢中進行計算量很大的計算,因此它可以在客戶端對它進行並行化(而不是在服務器/數據庫服務器端並行化)。

更好的答案可能是: PLINQ用於分發跨多個線程的計算密集型查詢。 異步是用於返回線程,以便其他人可以使用它,因爲您將等待外部資源(數據庫,磁盤I/O,網絡I/O等)。

異步PLINQ沒有非常強大的用例,在等待的時候你想要返回線程並且你有很多計算要做......如果你正忙於計算,你需要線程(或多個線程)。他們幾乎完全在優化的不同方面。如果你需要這樣的東西,有更好的機制,比如任務等。

+1

如果有人確實需要並行*和*異步功能,則TPL Dataflow是一個很好的庫。在這種情況下,PLINQ被操作誤用(我認爲是誤解)。 –

0

嗯,你不能。這些是兩個不同的選項,不會在一起。

您可以使用Task.Runasync-await並行異步操作的同步部分(即隨之而來的第一await前)在多個ThreadPool線程,但沒有內置到PLINQ所有分區的邏輯,例如:

var tasks = enumerable.Select(item => Task.Run(async() => 
{ 
    LongSynchronousPart(item); 
    await AsynchronouPartAsync(item); 
})); 
await Task.WhenAll(tasks); 

然而,在你的情況下(假設它是實體框架),使用PLINQ沒有價值,因爲沒有實際的並行工作。查詢本身在數據庫中執行。