2014-06-06 78 views
2

我写过一个从作为参数给出的文件中读取数据的进程。 我已经同步读取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方法

任何想法?

+1

使用* both * OutputDataReceived和BeginOutputReadLine()是一个错误。 –

+0

@HansPassant:谢谢你指出。但在这个例子http://msdn.microsoft.com/en-us/library/vstudio/system.diagnostics.process.beginoutputreadline,我发现两者都被使用。 – BinaryMee

+0

我也看到了这个问题,我用thread.sleep解决了它。也许输出事件是在单独的线程中引发的,这意味着任意延迟。这个API设计似乎强制这个错误,并使其不可避免。 – usr

回答

4

您可以直接从实际的输出流中直接读取(假设您使用.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。这意味着您需要等待,直到您获得所有数据而不是等待以完成,因为这两个数据可能不完全在同一时间。

+0

我正在使用.Net 3.5 :( – BinaryMee

0

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

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

我认为塞维的处理方式是优越的。我只是在这里记录这种行为。

相关问题