Pergunta

Currently I have this 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;

Then the user of this function works like:

private async void Foo_Click(object sender, RoutedEventArgs e)
{
    String output = await ExecuteCommand();
}

Now the problem is that I am getting this error:

A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll

Additional information: An attempt was made to transition a task to a final state when it had already completed

This problem is thrown when I use tcs.SetResult().

Foi útil?

Solução

The OutputDataReceived event happens on each line written to stdout (and then a final time with Data == null when it's done, as you seem to already know), so you're getting that exception because you're trying to do SetResult multiple times.

Assuming you want to keep the same structure for the code, your else clause should change from tcs.SetResult(e.Data.ToString()); to storing the line in e.Data in a StringBuffer or List or whatever (it doesn't include the newline, so if you want to preserve that, you'll need to add it back yourself).

Then your 'if' clause will do the tcs.SetResult(stringBuffer.ToString()); (or however you decided to store the lines) before doing the outputWaitHandle.Set()

Make sure you have RedirectStandardOutput = true and RedirectStandardError = false since otherwise the process may block if it writes enough stderr and you requested it to get redirected but haven't read it. For details about that, search for 'deadlock' in the doc @ http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror.aspx

Outras dicas

You're wrapping the Event-based Asynchronous Pattern ( EAP ).

Try this MSDN article: TPL and Traditional .NET Asynchronous Programming

Once you have a Task<T>, you can await it.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top