2012-04-15 70 views
4

例如,讓我們說我正在寫與下面的簽名(C#4所以沒有異步關鍵字)的方法:創建表示一系列連續任務的任務

public Task Refresh(); 

它會調用一個方法(它也返回Task)執行通信工作,然後運行任務延續以基於檢索到的數據更新某些內部狀態。 e.g:

public Task Refresh() 
{ 
    Task<MyData> commsTask = datasource.LoadData(); 
    Task handleDataTask = commsTask.ContinueWith(HandleNewData); 

    return ?; 
} 

如果我返回handleDataTask它的完成狀態正確跟蹤「刷新」操作的結果,但它不正確地報告它的啓動狀態。

我可以將它們都包裝在一個新的Task.Factory.StartNew中,並將它們作爲子任務創建,但是爲了鏈接某些任務延續而使用新線程似乎很浪費。

當然,有一個整潔有效的方式來與TPL做到這一點?

+0

你爲什麼關心國家? – svick 2012-04-15 10:26:52

+0

這樣的實現匹配方法簽名的隱式文檔?我不知道,問我的方法的消費者。 「Task.Status」屬性可能有100多種用途,我所知道的是我的方法應該返回一個正確跟在它的文檔後面的「Task」。 – Tyson 2012-04-15 10:34:57

回答

3

通常,Task.Status僅用於找出有關最終狀態。無論如何,你無法依靠Started這個任務,因爲這個狀態可能會隨時改變。

因爲這個事實,如果你返回的任務有一個「奇怪」的狀態,直到它完成,這並不重要。只有三個完成狀態(Completed,Canceled,Faulted)很重要。

+0

我同意3個最終狀態是重要的。但是不能保證最終的任務將會運行,所以通過返回鏈中的最終任務,你會冒着代表整個操作返回的'Task'實例永遠停留在'WaitingForActivation'中的風險。我沒有在示例中加入它,但如果任務先前的任務被取消,那麼Task Continuations可能不運行。 – Tyson 2012-04-16 10:55:45

+1

@Tyson,如果先行任務被取消,那麼繼續任務通常會運行。如果使用TaskContinuationOptions來修改它,則繼續也會被取消。因此,它不會被卡住在'WaitingForActivation'狀態(除非前件包含無限循環或死鎖)。 – svick 2012-04-16 12:10:20

+0

@svick嗯......我現在找不到參考資料,但我記得看到一個任務延續未運行的例子。雖然現在我想雖然它沒有運行,但它仍然像你說的那樣直接進入'Cancelled'狀態。我不知道,爲了表示整個序列而返回最後的任務還是很麻煩。 – Tyson 2012-04-16 12:26:00

0

我做了一些進一步的研究,並發現了類似的SO問題,以及一些博客文章:

Task chaining without TaskCompletionSource?

http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx

http://msmvps.com/blogs/jon_skeet/archive/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method.aspx

所以就有了一半的答案 - 你可以創建一個代表所有子任務的Task實例,無需將新線程作爲子任務進行後臺處理:只需使用TaskCompletionSource即可。下面簡單的例子應用到我的問題上面沒有失敗或取消處理:

public Task Refresh() 
{ 
    var refreshTaskSource = new TaskCompletionSource<object>(); 

    Task<MyData> commsTask = datasource.LoadData(); 
    Task handleDataTask = commsTask.ContinueWith(HandleNewData); 
    handleDataTask.ContinueWith(t => refreshTaskSource.SetResult(null)); 

    return refreshTaskSource.Task; 
} 

然而通過此方法返回的任務現在直接轉換從TaskStatus.WaitingForActivationTaskStatus.RanToCompletion(或存在故障/取消,如果我有處理這些場景) 。