2016-09-12 66 views
1

在我的應用程序中,我需要在某些設定的時間間隔內連續處理Work的部分作品。我原本寫了一個Task來持續檢查給定的Task.Delay以查看它是否完成,如果是這樣的話Work將被處理,對應於Task.Delay。這種方法的缺點是Task,當沒有Task.Delay完成時,檢查這些Task.Delays將處於假無限循環。應該/可以將這個「遞歸任務」表示爲任務連續?

爲了解決這個問題,我發現我可以根據需要創建一個「遞歸Task」(我不確定這是什麼術語)以給定間隔處理工作。

// New Recurring Work can be added by simply creating 
// the Task below and adding an entry into this Dictionary. 
// Recurring Work can be removed/stopped by looking 
// it up in this Dictionary and calling its CTS.Cancel method. 
private readonly object _LockRecurWork = new object(); 
private Dictionary<Work, Tuple<Task, CancellationTokenSource> RecurringWork { get; set; } 
... 
private Task CreateRecurringWorkTask(Work workToDo, CancellationTokenSource taskTokenSource) 
{ 
    return Task.Run(async() => 
    { 
     // Do the Work, then wait the prescribed amount of time before doing it again 
     DoWork(workToDo); 
     await Task.Delay(workToDo.RecurRate, taskTokenSource.Token); 

     // If this Work's CancellationTokenSource is not 
     // cancelled then "schedule" the next Work execution 
     if (!taskTokenSource.IsCancellationRequested) 
     { 
      lock(_LockRecurWork) 
      { 
       RecurringWork[workToDo] = new Tuple<Task, CancellationTokenSource> 
        (CreateRecurringWorkTask(workToDo, taskTokenSource), taskTokenSource); 
      } 
     } 
    }, taskTokenSource.Token); 
} 

如果/可這是與Task.ContinueWith鏈表示?這樣的實現會有什麼好處嗎?目前的實施有什麼重大錯誤嗎?

+0

您應該使用'ConcurrentDictionary'。 – SLaks

+0

你的「循環任務」只是一個循環中效率較低的版本「await」。 (但首先不要這樣做) – SLaks

+0

@KDecker:不,你應該使用'await'而不是'ContinueWith'。 –

回答

1

調用ContinueWith告訴Task在完成後立即調用您的代碼。這是遠比手動輪詢它更快

+0

通過手動輪詢你是指我使用'await Task.Delay'? //繼續使用它可以更有意義地在「Task」類型之間進行切換,例如「DoWorkTask.ContinueWith(Task.Delay).ContinueWith(DoWorkTask ....」)而不是在單個Task中等待? – KDecker

+0

不,我的意思是擺脫你的整個功能和延誤,並直接與原始任務一起工作(你的實際目標不明確)。 – SLaks