为什么即使在进程终止后仍未完成异步读取?

时间:2014-06-06 13:30:17

标签: c# process

我编写了一个Process,它从作为参数给出的文件中读取数据。 我已同步异步读取StandardOutput和StandardError。

public static string ProcessScript(string command, string arguments)
{
        Process proc = new Process();
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.StartInfo.RedirectStandardError = true;
        proc.StartInfo.FileName = command;
        proc.StartInfo.Arguments = arguments;
        proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
        proc.Start();
        string error = null;
        string output = null;
        proc.OutputDataReceived += (sender, outputLine) => 
        { 
            if (outputLine.Data != null) 
            {
                output += outputLine.Data;
            }
        };
        proc.BeginOutputReadLine();
        error = proc.StandardError.ReadToEnd();
        proc.WaitForExit();
        proc.Close();

        //I have not got entire Output
        return output;
} 

完成该过程后,我得到了输出。但并非完全如此。我只得到部分数据。 即使在进程完成任务之后,异步读取也没有结束,所以只有我得到部分数据。我需要完整的字符串。

编辑:

我正在使用.Net 3.5。我无法使用ReadToEndAsync方法

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

您可以直接从实际输出流中直接读取(假设您使用的是.NET 4.5,这要归功于其添加的异步功能),而不是处理事件并处理由此产生的问题。 / p>

public static string ProcessScript(string command, string arguments)
{
    Process proc = new Process();
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.StartInfo.FileName = command;
    proc.StartInfo.Arguments = arguments;
    proc.Start();

    var output = proc.StandardOutput.ReadToEndAsync();
    var error = proc.StandardError.ReadToEndAsync();
    proc.WaitForExit();
    proc.Close();
    var errorContent = error.Result;
    return output.Result;
}

此处Task所代表的ReadToEndAsync实际上不会完整,直到它具有其结果所代表的全部数据为止。这意味着您需要等待直到获得所有数据而不是等待才能完成,因为这两个可能不在同一时间

答案 1 :(得分:0)

According to this post事件处理程序可能在WaitForExit完成后触发。我试图找出如何使用Reflector,但我看不到它。无论如何,我亲身经历过这种情况。

这篇文章还讲述了如何处理这个问题的秘诀:显然,当没有更多的输入时,会使用null数据调用事件处理程序。所以你需要等待这种情况。

我认为Servy解决这个问题的方法更胜一筹。我只是在这里记录这种行为。

答案 2 :(得分:0)

重复https://stackoverflow.com/a/25772586/2065863

WaitForExit()返回WaitForExit(timeout)之后调用true(无参数):

if (process.WaitForExit(timeout) && process.WaitForExit())
{
    // do stuff: async read will be completed here
}

有关详细信息,请阅读此处的评论:https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx