2016-02-25 9 views
5
erhalten werden muss

Ich versuche, meinen ursprünglichen CodeFühren Sie eine Asynchron-Aufgaben Haufen, wenn eine bestimmte Ausführungsreihenfolge

for(var item in items) 
{ 
    dbAccess.Save(item); 
} 

die gut arbeitet, um asynchronize: Allerdings

var tasks = new List<Task>(); 

    for(var item in items) 
    { 
     tasks.Add(dbAccess.SaveAsync(item)); 
    } 

    await Task.WhenAll(tasks); 

, ich brauche eine hinzufügen zusätzlicher Anruf Bereinigungs bevor ich spare und Element in meine DB:

var tasks = new List<Task>(); 

    for(var item in items) 
    { 
     tasks.Add(dbAccess.DeleteAsync(item.id)); 
     tasks.Add(dbAccess.SaveAsync(item)); 
    } 

    await Task.WhenAll(tasks); 

Dieser Code oben ist falsch, da SaveAs ync sollte nicht ausgeführt werden, bis das entsprechende DeleteAsync beendet ist. Mit anderen Worten, die Löschung muss immer vor dem Speichern für jeden Artikel ausgeführt werden, aber die Reihenfolge der Artikel spielt keine Rolle.

Gibt es einen perfekten Weg, dies zu tun?

+1

Wie wäre es mit der Ausgabe aller Löschungen zuerst, warten auf sie, dann alle Saves ausgeben und dann auf diese warten? Andernfalls sollten Sie jedes Löschen + Speichern in eine einzelne Aufgabe packen. –

+0

Guter Punkt Lasse, ich habe meinen Code für den Zweck dieser Frage vereinfacht. Ich kann Ihren Vorschlag nicht umsetzen, weil es ein bisschen mehr gibt, das ich nicht zeige. Tatsächlich gibt DeleteAsync etwas anderes zurück, das an SaveAsync übergeben werden muss. – AstroSharp

+0

Also? Packen Sie sie in eine Aufgabe, die zuerst deleteasync aufruft und anschließend saveasync aufruft? –

Antwort

6

Eine async Methode, die das Löschen durchführt, dann die speichern, für ein einzelnes Element, und führen Sie alle diese zusammengesetzten Operationen für jedes Element parallel:

var tasks = items.Select(async item => 
{ 
    await dbAccess.DeleteAsync(item.id); 
    await dbAccess.SaveAsync(item); 
}); 
await Task.WhenAll(tasks); 
2

Sie können eine Func<Task> verwenden, um die zwei Asynchron-einzukapseln ruft zu einem einzigen Task wie folgt aus:

for(var item in items) 
{ 
    //We store the value of item in a local variable 
    //because it is not recommended to close over a loop variable 
    var my_item = item; 

    Func<Task> task_fact = async() => 
    { 
     await dbAccess.DeleteAsync(my_item.id); 
     await dbAccess.SaveAsync(my_item); 
    }; 

    tasks.Add(task_fact()); 
} 

dies eine Aufgabe erstellen wird, die die Löschmethode aufruft, asynchron auf ihn warten, und ruft dann das Speichern Methode und warten Sie asynchron darauf.

Sie können das Gleiche mit einer Methode tun.

1

Wie wäre es mit ContinueWith:

var tasks = new List<Task>(); 

for(var item in items) 
{ 
    var task = dbAccess.DeleteAsync(item.id) 
      .ContinueWith(antecedent => dbAccess.SaveAsync(item)) 
      .Unwrap(); 

    tasks.Add(task); 
} 

await Task.WhenAll(tasks); 
+0

Sie müssen das Ergebnis auspacken, da Sie derzeit nicht darauf warten, dass der Speichervorgang abgeschlossen wird. Es ist auch viel unordentlicher als mit "erwarten" und hat wahrscheinlich nicht die Fehlerbehandlung Semantik, die Sie wollen. – Servy

Verwandte Themen