Wie async serialisieren / warten?

8

Nehmen wir an, ich habe dieses einfache Snippet:

%Vor%

Offensichtlich wird jedes Mal, wenn ich diesen Knopf drücke, eine neue Aufgabe gestartet, selbst wenn eine vorherige Aufgabe noch läuft. Wie würde ich eine neue Aufgabe verschieben, bis alle vorherigen Aufgaben beendet sind?

Einige weitere Details:

Im obigen Beispiel ist jede neue Aufgabe identisch mit der vorherigen Aufgabe. Im ursprünglichen Kontext spielt jedoch die Abfolge der Aufgaben eine Rolle: Die Parameter können sich ändern (ich könnte sie mit DateTime.Now.Ticks "simulieren"). Die Aufgaben sollten in der Reihenfolge ausgeführt werden, in der sie "registriert" sind. Speziell wird mein Programm mit einem seriellen Gerät sprechen. Ich habe das schon mal mit einem Hintergrund-Thread gemacht, der ein BlockingCollection benutzt. Dieses Mal gibt es jedoch ein striktes Anfrage / Antwort-Protokoll und ich möchte async / wait verwenden, wenn es möglich ist.

Mögliche Lösung:

Ich könnte mir vorstellen, Aufgaben zu erstellen und sie in einer Liste zu speichern. Aber wie würde ich die Aufgaben in Bezug auf die Anforderungen ausführen? Oder sollte ich zu der Thread-basierten Lösung zurückkehren, die ich zuvor verwendet habe?

    
JeffRSon 16.01.2014, 13:28
quelle

4 Antworten

6

Sie könnten auf ein SemaphoreSlim asynchron warten und es freigeben, sobald der Job fertig ist. Vergessen Sie nicht, die Semaphor-Anfangszahl auf 1 zu konfigurieren.

%Vor%     
Sriram Sakthivel 16.01.2014, 13:34
quelle
8

Ich empfehle die Verwendung von SemaphoreSlim für die Synchronisation. Sie möchten jedoch vermeiden Task.Factory.StartNew (wie ich auf meinem Blog erkläre), und auch definitiv vermeide async void (wie ich im MSDN Artikel).

%Vor%     
Stephen Cleary 16.01.2014 13:55
quelle
2

Wie wäre es mit dem Dataflow.ActionBlock<T> mit dem (voreingestellten) maximalen Parallelitätsgrad von 1.? Auf diese Weise müssen Sie sich nicht um die Threadsicherheit / Sperrprobleme kümmern.

Es könnte etwa so aussehen:

%Vor%

Sie können den ActionBlock auch so einrichten, dass er ein Task oder Func<Task> erhält und einfach / diese Eingabe ausführen. Dadurch könnten mehrere Vorgänge aus verschiedenen Quellen in die Warteschlange gestellt und abgewartet werden.

    
Andrew Hanlon 17.01.2014 16:25
quelle
2

Ich könnte etwas übersehen haben, aber ich denke nicht, dass SemaphoreSlim für das OP-Szenario benötigt wird. Ich würde es so machen. Im Grunde ist der Code nur await der vorherigen ausstehenden Instanz der Aufgabe vor dem Fortfahren (keine Ausnahmebehandlung für Klarheit):

%Vor%

[UPDATE] Um den Kommentar zu adressieren, ist hier eine Thread-sichere Version, wenn button_Click gleichzeitig aufgerufen werden kann:

%Vor%     
Noseratio 17.01.2014 06:04
quelle

Tags und Links