0

目前我有这个代码:

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();
}

现在的问题是我收到了这个错误:

mscorlib.dll 中出现“System.InvalidOperationException”类型的第一次机会异常 mscorlib.dll 中出现“System.InvalidOperationException”类型的未处理异常

附加信息:尝试将已完成的任务转换为最终状态

当我使用tcs.SetResult().

4

2 回答 2

2

您正在包装基于事件的异步模式 ( EAP )。

试试这篇 MSDN 文章:TPL 和传统的 .NET 异步编程

一旦你有了一个Task<T>,你就可以await了。

于 2012-02-19T12:10:36.467 回答
1

OutputDataReceived 事件发生在写入标准输出的每一行上(然后在完成后最后一次使用 Data == null,正如您似乎已经知道的那样),因此您收到该异常,因为您尝试多次执行 SetResult .

假设您想为代码保持相同的结构,您的 else 子句应该从 tcs.SetResult(e.Data.ToString()); 将 e.Data 中的行存储在 StringBuffer 或 List 或其他任何东西中(它不包括换行符,所以如果你想保留它,你需要自己添加回来)。

然后你的'if'子句将执行 tcs.SetResult(stringBuffer.ToString()); (或者您决定存储这些行)在执行 outputWaitHandle.Set() 之前

确保你有 RedirectStandardOutput = true 和 RedirectStandardError = false 否则如果进程写了足够的标准错误并且你请求它被重定向但没有读取它,它可能会阻塞。有关详细信息,请在文档中搜索“死锁”@ http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror.aspx

于 2012-02-19T18:46:45.277 回答