Pregunta

Actualmente tengo este código:

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;

Entonces el usuario de esta función funciona como:

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

Ahora el problema es que recibo este error:

Una excepción de primera oportunidad del tipo 'System.InvalidOperationException' ocurrió en mscorlib.dll una excepción no controlada del tipo 'System.InvalidOperationException' ocurrió en mscorlib.dll

Información adicional: se intentó hacer la transición de una tarea a un estado final cuando ya había completado

Este problema se arroja cuando uso tcs.SetResult().

¿Fue útil?

Solución

El evento OutputDatarCeived ocurre en cada línea escrito en Stdout (y luego una última vez con Data == NULL cuando está hecho, como parece que ya sabe), por lo que está obteniendo esa excepción porque está tratando de hacer SetResult varias veces .

Suponiendo que desea mantener la misma estructura para el código, su cláusula más debe cambiar de tcs.setResult (e.data.ToString ()); Para almacenar la línea en E.Data en una lista o lista o lo que sea (no incluye la nueva línea, por lo que si desea preservarla, deberá agregarla usted mismo).

Entonces su cláusula 'If' hará el tcs.setResult (stringBuffer.ToString ()); (o sin embargo, decidió almacenar las líneas) antes de hacer el outputwaithandle.set ()

Asegúrese de tener redirectionStandoDoutput = True y redirectAntandarderRor = falso, ya que de lo contrario el proceso puede bloquear si escribe suficiente stderr y solicitó que se redirle pero no lo haya leído. Para obtener detalles sobre eso, busque 'Deadlock' en el documento @ http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror.aspx

Otros consejos

Estás envolviendo el patrón asíncrono basado en eventos (EAP).

Prueba este artículo de MSDN: TPL y programación asincrónica .NET tradicional

Una vez que tengas un Task<T>, puedes await eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top