Wie warten Sie in C#"process.outputDatarecebed"?
-
27-10-2019 - |
Frage
Derzeit habe ich diesen Code:
TaskCompletionSource<String> tcs = new TaskCompletionSource<String>();
// ...
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
tcs.SetResult(e.Data.ToString());
}
};
// ...
return tcs.Task;
Dann funktioniert der Benutzer dieser Funktion wie:
private async void Foo_Click(object sender, RoutedEventArgs e)
{
String output = await ExecuteCommand();
}
Das Problem ist nun, dass ich diesen Fehler bekomme:
Eine Ausnahme der ersten Chance von Typ 'system.invalidoperationException' trat in mscorlib.dll auf. Eine nicht behandelte Ausnahme des Typs 'System.invalidoperationException' trat in mscorlib.dll auf
Zusätzliche Informationen: Es wurde versucht, eine Aufgabe in einen endgültigen Zustand zu übergeben, als sie bereits abgeschlossen war
Dieses Problem wird geworfen, wenn ich benutze tcs.SetResult()
.
Lösung
Das OutputDatarecebed -Ereignis erfolgt in jeder Zeile, die an STDOut geschrieben wurde (und dann ein letztes Mal mit Data == NULL, wenn es fertig ist, wie Sie es anscheinend bereits wissen) .
Angenommen, Sie möchten die gleiche Struktur für den Code beibehalten, sollte sich Ihre sonstige Klausel von tcs.setResult (e.data.tostring ()) ändern; Um die Linie in E.Data in einem StringBuffer oder einer Liste oder was auch immer zu speichern (es enthält nicht die Newline. Wenn Sie dies beibehalten möchten, müssen Sie sie selbst wieder hinzufügen).
Dann wird Ihre "if" -Klausel das tcs.setResult (Stringbuffer.toString ()) erledigen; (oder wie auch immer Sie sich entschieden haben, die Linien zu speichern), bevor Sie den outputWaithandle.set () durchführen
Stellen Sie sicher, dass Sie recirectStandardoutput = true und recirectStandardError = false haben, da sonst der Vorgang blockiert werden kann, wenn er genügend Stderr schreibt, und Sie haben ihn angefordert, um umgeleitet zu werden, aber nicht gelesen. Weitere Informationen dazu suchen Sie nach "Deadlock" im Doc @ http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror.aspx
Andere Tipps
Sie wickeln das ereignisbasierte asynchrone Muster (EAP) ein.
Probieren Sie diesen MSDN -Artikel aus: TPL und herkömmliche .NET -Asynchronprogrammierung
Sobald Sie eine haben Task<T>
, du kannst await
es.