2017-08-26 23 views
1

我試圖想出運行異步方法迭代的最佳方法。 基本上,我得到第一個TimeSpanDictionary<Item,TimeSpan>在第一個時間段內運行。無限期運行異步方法迭代(使用嵌套迭代)

例如:

var iteration = new TimeSpan().FromSeconds(60); 

var items = new Dictionary<Item,TimeSpan>(); 
items.Add(item1,new TimeSpan().FromSeconds(10)) 
items.Add(item2,new TimeSpan().FromSeconds(30)) 

它是安全的假設:

  • 字典中的項目TimeSpan總是<iteration
  • iteration,當轉換爲秒,總適合NTimeSpan字典中的項目(如果迭代比項目的時間跨度長60秒1或2或3或6或10或15等。

對於每個Item我需要運行的異步方法每隔X毫秒(通過在字典中TimeSpan所定義,例如:

public async Task<int> MyMethod(Item item) 
{ 
    return await 3; // In reality something is done and a result is returned 
} 

這意味着對於本例中的兩個項目和在60秒的時間跨度,如果我在T00:00開始我需要爲item1 6次運行MyMethodT00:00和(在T00:00T00:10T00:20等)和item2 2倍()。

現在,這部分是比較簡單的,我正在努力的一點是使iteration在60秒內重複,並確保它開始是否前一個完成與否。例如,如果MyMethoditem1需要12秒來完成我仍然希望60秒之後開始另一次迭代(這意味着在某一時間點我將具有MyMethod一個以上執行對item1活性。


東西,我試圖做的是遞歸void調用MyMethodContinueWith(() => { MyMethod(item),但不能讓它的工作。

+0

你有沒有用定時器試試Rx? – VMAtm

回答

1

其實我已經解決了自己的問題。 Iteration是代表一個迭代的一類:

public void RunIterations() 
{ 
    var iterations = new List<Iteration>(); 

    // Adding items that represent the iterations to run 

    // Here we're creating an array of tasks for each iteration 
    // The running RunIteration for each iteration that needs to be created 
    // However, the tasks will never finish unless the cancellation is requested (as we can see in RunIteration method). 
    var iterationTasks = new Task[iterations.Count]; 

    var iterationIndex = 0; 
    foreach (Iteration iteration in iterations) 
    { 
     iterationTasks[iterationIndex] = RunIteration(iteration); 
     iterationIndex++; 
    } 

    Task.WaitAll(iterationTasks); 
} 

private async Task RunIteration(Iteration iteration) 
{ 
     // We're creating an endless loop that will keep starting the RunAsync() for the iteration until the cancellation is requested. 
     while (!_cancellationTokenSource.IsCancellationRequested) 
     { 
      // We're running the RunAsync() without waiting for it to finish. 
      // It's done on purpose: in case any stages in the iteration take more time than expected 
      // then another iteration is started in parallel as the previous one is finishing. 
      iteration.RunAsync().ContinueWith(
       task => { 
        DoSomethingWithResult(task.Result); 
       }); 

      // Waiting for the duration of the iteration to start the next one. 
      await Task.Delay((new TimeSpan().FromSeconds(60)); 
     } 
}