8

Was ist, wenn Sie mehrere asynchrone E/A-Aufgaben parallel ausführen müssen, aber sicherstellen müssen, dass nicht mehr als X-E/A-Prozesse gleichzeitig ausgeführt werden; und vor und nach E/A-Verarbeitungsaufgaben sollte keine solche Beschränkung haben.Wie werden mehrere asynchrone Tasks parallel ausgeführt?

Hier ist ein Szenario - sagen wir, es gibt 1000 Aufgaben; jeder von ihnen akzeptiert eine Textzeichenfolge als Eingabeparameter; wandelt diesen Text um (vor E/A-Verarbeitung) und schreibt diesen umgewandelten Text in eine Datei. Das Ziel besteht darin, dass die Vorverarbeitungslogik 100% der CPU/Kerne und den E/A-Teil der Tasks mit maximal 10 Grad Parallelität nutzt (maximal 10 gleichzeitig zum Schreiben von Dateien gleichzeitig geöffnet).

Können Sie einen Beispielcode zur Verfügung stellen, wie man es mit C#/.NET 4.5 macht?

http://blogs.msdn.com/b/csharpfaq/archive/2012/01/23/using-async-for-file-access-alan-berman.aspx

+0

Rx 2.0 könnte eine gute Passform für diese sein (die zweite Stufe 10 zu einer Zeit Drosselung), aber ich bin nicht vertraut genug damit um sicher zu sein. : -/ –

Antwort

7

Ich denke, mit TPL Dataflow wäre dies eine gute Idee: Sie erstellen Pre-und Post-Prozess-Blöcke mit unbegrenzter Parallelität, einen Datei-Schreib-Block mit begrenzter Parallelität und verknüpfen sie miteinander. Etwas wie:

var unboundedParallelismOptions = 
    new ExecutionDataflowBlockOptions 
    { 
     MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded 
    }; 

var preProcessBlock = new TransformBlock<string, string>(
    s => PreProcess(s), unboundedParallelismOptions); 

var writeToFileBlock = new TransformBlock<string, string>(
    async s => 
      { 
       await WriteToFile(s); 
       return s; 
      }, 
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 }); 

var postProcessBlock = new ActionBlock<string>(
    s => PostProcess(s), unboundedParallelismOptions); 

var propagateCompletionOptions = 
    new DataflowLinkOptions { PropagateCompletion = true }; 

preProcessBlock.LinkTo(writeToFileBlock, propagateCompletionOptions); 
writeToFileBlock.LinkTo(postProcessBlock, propagateCompletionOptions); 

// use something like await preProcessBlock.SendAsync("text") here 

preProcessBlock.Complete(); 
await postProcessBlock.Completion; 

Wo WriteToFile() könnte wie folgt aussehen:

private static async Task WriteToFile(string s) 
{ 
    using (var writer = new StreamWriter(GetFileName())) 
     await writer.WriteAsync(s); 
} 
+0

+1 Das ist interessant .. danke! –

+0

Was sind die 'PreProcess' und' PostProcess' Methoden hier? – shashwat

+0

@shashwat Sie tun, was auch immer benötigt wird. Die ursprüngliche Frage bezieht sich auf "Pre- und Post-I/O-Verarbeitungsaufgaben", also habe ich das mit Methoden dargestellt. – svick

1

Es klingt wie Sie eine Djikstra Semaphore betrachten würden wollen Zugang zum Starten von Tasks zu steuern.

Dies klingt jedoch wie eine typische Warteschlange/feste Anzahl von Verbrauchern Art von Problem, das eine geeignetere Methode sein kann, um es zu strukturieren.

Verwandte Themen