Führen Sie eine Reihe von Aufgaben nacheinander aus

Führen Sie eine Reihe von Aufgaben nacheinander aus

Der einfache Weg (mit Microsoft.Bcl.Async ):

static async Task<TState> AggregateAsync<T, TState>(
    this IEnumerable<T> items,
    TState initial,
    Func<TState, T, Task<TState>> makeTask)
{
  var state = initial;
  foreach (var item in items)
    state = await makeTask(state, item);
  return state;
}

Auf die harte Tour:

static Task<TState> AggregateAsync<T, TState>(
    this IEnumerable<T> items,
    TState initial,
    Func<TState, T, Task<TState>> makeTask)
{
  var tcs = new TaskCompletionSource<TState>();
  tcs.SetResult(initial);
  Task<TState> ret = tcs.Task;
  foreach (var item in items)
  {
    var localItem = item;
    ret = ret.ContinueWith(t => makeTask(t.Result, localItem)).Unwrap();
  }
  return ret;
}

Beachten Sie, dass die Fehlerbehandlung auf dem "harten" Weg umständlicher ist; eine Ausnahme vom ersten Element wird in AggregateException eingeschlossen durch jeden aufeinanderfolgenden Artikel. Der "einfache" Weg schließt solche Ausnahmen nicht ein.


Sie können Task.ContinueWith verwenden . Die task Sie sehen im Code unten, stellt die vorherige (abgeschlossene) Aufgabe dar, und Sie können ihr Ergebnis abrufen, um die zweite Aufgabe auszuführen, und so weiter.

T item1 = default(T);
T item2 = default(T);
Task<TState> task1 = makeTask(initial, item1);

//create second task
task1.ContinueWith(task => makeTask(task.Result, item2).Result,
                     TaskContinuationOptions.OnlyOnRanToCompletion);

Bearbeiten

Tut mir leid, ich habe diesen Teil verpasst

Dazu müssen Sie lediglich eine Referenz auf das Ergebnis der letzten ContinueWith zurückgeben anrufen.

Task<State> aggregate = task1.ContinueWith(
                                  task => makeTask(task.Result, item2).Result,
                                  TaskContinuationOptions.OnlyOnRanToCompletion);

var res = aggregate .Result; //wait synchronously for the result of the sequence