2017-08-09 1 views
2

Ich habe eine BroadcastBlock mit ActionBlock verbunden. Wenn ich sequentiell sowohl auf BroadcastBlock als auch auf ActionBlock "complete" anrufe, funktioniert es nicht. Während das Aufrufen von "complete" auf BroadCastBlock allein funktioniert, funktioniert.Linked DataFlow Block Fertigstellung funktioniert nicht

public class ActionTester 
{ 
    private readonly ActionBlock<int> _action; 
    private readonly BroadcastBlock<int> _input; 

    public ActionTester() 
    { 
     _input = new BroadcastBlock<int>(null); 
     _action = new ActionBlock<int>(i => Process(i)); 

     _input.LinkTo(_action, new DataflowLinkOptions { PropagateCompletion = true }); 
    } 

    public void Post(int i) => _input.Post(i); 

    public async Task Process(int i) 
    { 
     await Task.Delay(2000); 
     Console.WriteLine(i); 
    } 

    public void Complete() 
    { 
     _input.Complete(); 
     _action.Complete(); // When this is removed, program is working as expected 
    } 

    public Task Completion => _action.Completion; 
} 

Der Testcode ist

static void Main(string[] args) 
{ 
    var actor = new ActionTester(); 

    actor.Post(5); 
    actor.Post(7); 

    actor.Complete(); 
    actor.Completion.Wait(); 

    Console.WriteLine("Finished"); 
    Console.Read(); 
} 

Wenn _action.Complete() vorhanden (kommentierte Linie), Code bewegt Vergangenheit actor.Completion.wait() und "Fertig" angezeigt bekommen. Wenn ich _aciton.Complete() entferne, werden die geposteten Werte richtig angezeigt und dann wird "Beendet" geschrieben.

Wenn Datenflussblöcke verknüpft sind, sollten wir nur "Complete" des Root-Blocks aufrufen? Die Einstellung PropagateCompletion auf wahr/falsch hat keine Auswirkungen.

Lösung

Gelöst für den Root-Block Abschluss durch das Warten

public void Complete() 
{ 
    _input.Complete(); 
    _input.Completion.Wait(); 
    _action.Complete(); 
} 

Antwort

2

Wenn Datenfluß Blöcke verbunden sind, sollten wir nur gerade "Complete" nennen des Root-Block?

Ja, genau das sollten Sie tun.

Wenn Sie das tun Completion propagieren, dann tun Sie nicht brauchen _actionBlock selbst abzuschließen - es abgeschlossen wird, nachdem alle Elemente aus dem Puffer verarbeitet werden. Nachdem Sie den Aktionsblock abgeschlossen haben, akzeptiert er keine neuen Nachrichten mehr. Das beschriebene Verhalten ist daher erwartet und gültig.

+0

Wenn "PropogateCompletion" auf false gesetzt ist, sollten wir nicht alle verknüpften Blöcke als abgeschlossen bezeichnen? In meinem Beispiel, selbst wenn ich PropagateCompletion auf false gesetzt habe, funktionierte es nicht, wenn ich einen weiteren Aufruf für den verknüpften Block abgeschlossen habe. – Saravanan

+0

Wenn Sie den zweiten Block ** vor ** abschließen, werden alle Nachrichten von der ersten an die zweite gesendet, die zweite Nachricht verwirft alle. Also, wenn Sie die Fertigstellung nicht weitergeben, müssen Sie es selbst behandeln. – VMAtm

Verwandte Themen