2014-10-07 114 views
1

我一直在尋找一個解決方案,現在看來似乎必須是一個簡單的問題。然而,我發現每一個例子創建的Task同樣的情形這一個(從How to: Extend the Async Walkthrough by Using Task.WhenAll (C# and Visual Basic)頁面上MSDN拍攝)集合:等待幾種不同異步操作的結果使用Task.WhenAny

IEnumerable<Task<int>> downloadTasksQuery = 
    from url in urlList select ProcessURLAsync(url); 

我不能這樣做,因爲我想調用不同async方法和await結果......更多的東西像這樣的(但不是這一點,因爲這似乎並沒有做任何事情):

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>(); 
getTicketTasks.Add(new Task(() => Model.GetTicketsAsync(eventDate))); 
getTicketTasks.Add(new Task(() => Model.GetGuestTicketsAsync(eventDate))); 
... 
getTicketTasks.Add(new Task(() => Model.GetOtherTicketsAsync(eventDate))); 

IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks); 

所以,我怎麼能叫一些async方法和await使用Task.WhenAll方法的結果?

+0

什麼是'GetTicketsAsync','GetGuestTicketsAsync'的返回類型..? – 2014-10-07 14:12:16

+0

'任務>' – Sheridan 2014-10-07 14:12:38

回答

7

請勿使用該任務構造函數來調用異步方法*。只需使用Task.WhenAll一起調用這些方法,存儲返回的任務,await所有的人:

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>(); 
getTicketTasks.Add(Model.GetTicketsAsync(eventDate)); 
getTicketTasks.Add(Model.GetGuestTicketsAsync(eventDate)); 
... 
getTicketTasks.Add(Model.GetOtherTicketsAsync(eventDate)); 

IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks); 

在創建任務的情況下,但你不啓動它,因此它不運行。如果您確實啓動了它,則只需簡單地啓動實際的異步操作,而無需在任何地方存儲返回的任務這意味着你沒有任何東西await。您正在等待的所有任務都會觸發並忘記另一個async操作。

Task.WhenAll還與params過載使另一個選擇是:

var tickets = await Task.WhenAll(
    Model.GetTicketsAsync(eventDate), 
    Model.GetGuestTicketsAsync(eventDate), 
    Model.GetOtherTicketsAsync(eventDate)); 

*或任何其他情況下,爲這一問題。

+1

+1感謝您的回覆如此之快...雖然我不得不承認,嘗試閱讀您的回覆時,您仍然每隔幾秒鐘更新一次,真的很痛苦......我會個人更喜歡等一會兒,並一口氣讀完,但也許我應該稍後再回來?無論哪種方式,您的解決方案似乎工作,所以謝謝。 – Sheridan 2014-10-07 14:33:43

+0

@Sheridan做任何適合你的工作。只要你回答人們可能有的澄清問題,你就可以在幾小時後閱讀。 – i3arnon 2014-10-07 14:36:10

2

您剛剛創建的Task。你從未開始過。通過構造函數創建Task將不會啓動Task,因此也不會轉換爲完成狀態。所以等待它將會持續下去。

使用Task.Run或致電Task.Start但是不建議使用Task.Start。優先選擇Task.Run以啓動異步操作。如果您已經有Task<T>只需創建一個數組並等待它。

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>(); 
getTicketTasks.Add(Model.GetTicketsAsync(eventDate)); 
getTicketTasks.Add(Model.GetGuestTicketsAsync(eventDate)); 
... 
getTicketTasks.Add(Model.GetOtherTicketsAsync(eventDate)); 
IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks); 
+1

在這種情況下沒有理由使用'Task.Run'。 – i3arnon 2014-10-07 14:24:00

+1

@ I3arnon儘管名稱爲「Async」,但我認爲OP有同步方法。稍後在確認它是'任務'我更新了我的答案並刪除了代碼中的Task.Run。 – 2014-10-07 14:29:36

+1

+1是的,那是我的不好...我錯誤地回答了他的問題 - 對不起。 – Sheridan 2014-10-07 14:32:55