2016-11-25 2 views
1

In meiner ASP.NET-API erhalte ich eine Reihe von Nachrichten, die beibehalten werden sollen. In diesem speziellen Fall ersetzt die Reaktionsfähigkeit der API die Wichtigkeit jeder einzelnen Nachricht. Anstatt also direkt in meinen Datenspeicher zu schreiben, schiebe ich die eingehenden Nachrichten in eine Warteschlange und bearbeite sie so schnell wie möglich in einem Hintergrundthread.Verwenden von TaskCompletionSource mit einer Warteschlange und einem Hintergrundthread

In einigen Fällen kann ich eine Notwendigkeit, den Erfolg oder Misserfolg des Schreibvorgangs zu bestätigen, so dass ich meine Nachricht in einer benutzerdefinierten Message Objekt wickeln, das den folgenden Code verwendet:

public class WriteMessageContext 
{ 
    public Message Message { get; private set; } 
    TaskCompletionSource<bool> complete = new TaskCompletionSource<bool>(); 

    public WriteMessageContext(Message message) 
    { 
     Message = message; 
    } 

    public Task<bool> WaitForInsert() 
    { 
     return complete.Task; 
    } 

    public void Success() 
    { 
     complete.SetResult(true); 
    } 

    public void Error() 
    { 
     complete.SetResult(false); 
    } 
} 

Der Erfolg und die Fehlermethoden sollen vom Worker-Thread aufgerufen werden, der jede in der Warteschlange befindliche Nachricht im Hintergrund verarbeitet. Dann in meinem Controller, kann ich:

var ctx = new WriteMessageContext(msg); 
queue.Enqueue(ctx); 

// optionally... 
if (await ctx.WaitForIt()) { 
    // successful 
} else { 
    // or not 
} 

Ist dies eine angemessene Nutzung von TaskCompletionSource + async/erwarten, oder ich bin bastardizing es mit wreckless verlassen? Gibt es irgendwelche potenziellen Probleme, die ich damit umgehen sollte?

+1

Ich würde die Flags 'TaskCreationOptions.RunContinuationsAsynchronChrome' und 'TaskCreationOptions.DenyChildAttach' empfehlen. –

Antwort

1

Für mich ist es eine gültige Verwendung von TaskCompletionSource<T>.

BTW, vielleicht werden Sie überrascht, weil es eine versteckte Eigenschaft/Edelstein vorhanden in Task Parallel Library (TPL) data-flow blocks.

Eigentlich ist es eine, die Ihren Anforderungen entsprechen können: BufferBlock<T>:

Die BufferBlock<T>-Klasse stellt eine Allzweck- asynchrones Messaging-Struktur. Diese Klasse speichert eine FIFO-Warteschlange (First In First Out) von Nachrichten, in die von mehreren Quellen geschrieben oder von mehreren Zielen gelesen werden kann. Wenn ein Ziel eine Nachricht von einem Objekt BufferBlock<T> empfängt, wird diese Nachricht aus der Nachrichtenwarteschlange entfernt. Obwohl ein BufferBlock<T> Objekt mehrere Ziele haben kann, empfängt daher nur ein Ziel jede Nachricht. Die Klasse BufferBlock<T> ist nützlich, wenn Sie mehrere Nachrichten an eine andere Komponente übergeben möchten und diese Komponente jede Nachricht empfangen muss.

+0

Wusste nicht einmal, dass es existiert. Ich sollte das wahrscheinlich verwenden, anstatt eine ConcurrentQueue abzufragen, wie ich es jetzt bin. – Chris

+0

@Chris ja, es ist nicht die beliebteste Funktion in .net, aber es ist immer noch da für uns;) –

Verwandte Themen