为什么即使在进程终止后,异步读取也没有完成

本文关键字:读取 异步 进程 终止 为什么 | 更新日期: 2023-09-27 18:07:00

我写了一个从文件中读取数据作为参数的进程。我异步读取了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方法

任何想法?

为什么即使在进程终止后,异步读取也没有完成

不需要处理事件,也不需要处理由此产生的问题,您可以直接从实际的输出流中读取(假设您使用的是。net 4.5,由于它增加了异步功能)。

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

在这里,ReadToEndAsync所代表的Task直到得到其结果所代表的全部数据才真正完成。这意味着您正在等待直到您拥有所有的数据,而不是等待进程完成,因为这两者可能不完全同时。

根据这篇文章,事件处理程序可能在WaitForExit完成后触发。我试图找出如何使用反射器,但我看不见它。不管怎样,我自己也经历过这种事。

这篇文章还告诉了如何处理这个问题的秘密:显然,当没有更多的输入将到来时,事件处理程序将使用null数据调用。因此,您需要等待这个条件。

我认为Servy处理这件事的方式是优越的。我只是在记录这个行为

https://stackoverflow.com/a/25772586/2065863副本

WaitForExit(timeout)返回true后直接调用WaitForExit()(不带参数):

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