Как «ждать» «process.OutputDataReceived» событие в C #? - PullRequest
0 голосов
/ 19 февраля 2012

В настоящее время у меня есть этот код:

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;

Тогда пользователь этой функции работает так:

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

Теперь проблема в том, что я получаю эту ошибку:

Первое случайное исключение типа «System.InvalidOperationException» произошло в mscorlib.dll Произошло необработанное исключение типа «System.InvalidOperationException» в mscorlib.dll

Дополнительная информация: Была предпринята попыткачтобы перевести задачу в конечное состояние, когда она уже выполнена

Эта проблема возникает при использовании tcs.SetResult().

Ответы [ 2 ]

2 голосов
/ 19 февраля 2012

Вы переносите асинхронный шаблон на основе событий (EAP).

Попробуйте эту статью MSDN: TPL и традиционное .NET асинхронное программирование

Как толькоTask<T>, вы можете await это.

1 голос
/ 19 февраля 2012

Событие OutputDataReceived происходит в каждой строке, записанной в stdout (а затем в последний раз с Data == null, когда это будет сделано, как вы, кажется, уже знаете), поэтому вы получаете это исключение, потому что вы пытаетесь сделать SetResult несколько раз.

Предполагая, что вы хотите сохранить ту же структуру для кода, ваше предложение else должно измениться на tcs.SetResult (e.Data.ToString ()); для сохранения строки в e.Data в StringBuffer или List или где-либо еще (в нее не входит перевод строки, поэтому, если вы хотите сохранить ее, вам нужно будет добавить ее обратно самостоятельно).

Тогда ваше предложение if выполнит tcs.SetResult (stringBuffer.ToString ()); (или, тем не менее, вы решили сохранить строки) перед выполнением outputWaitHandle.Set ()

Убедитесь, что у вас есть RedirectStandardOutput = true и RedirectStandardError = false, поскольку в противном случае процесс может блокироваться, если он пишет достаточно stderr, и вы запросили его перенаправить, но не прочитали его. Подробнее об этом ищите в тупике в документе @ http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror.aspx

...