process.OutputDataReceived没有读取所有行

时间:2013-05-11 09:28:50

标签: c#

来自cmd的结果

C:\Users\XXXXX>adb start-server
* daemon not running. starting it now *
* daemon started successfully *

C:\Users\XXXXX>

我的c#代码。

public string devicesPlus()
{
    psi.Arguments = "start-server";
    call = Process.Start(psi);
    call.OutputDataReceived += new DataReceivedEventHandler(call_OutputDataReceived);
    call.ErrorDataReceived += new DataReceivedEventHandler(call_OutputDataReceived);
    call.EnableRaisingEvents = true;
    call.Exited += new EventHandler(call_Exited);
    call.Start();
    call.BeginOutputReadLine();
    call.BeginErrorReadLine();
    call.StandardInput.Close();
    call.WaitForExit();
    return outData.ToString();
}

private void call_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    if (e.Data != null)
    {
        outData.Append(e.Data);
    }
}

现在当我调用devicesPlus时,有时候我只得到*守护进程没有运行。立即开始* 有一段时间它只是在后台工作而没有结果.. 你能告诉我我的代码中有什么不对,为什么我没有像cmd那样得到正确的回报.. 新来的c#抱歉英语不好......

更新 如果我从我的应用程序外部杀了adb,我会突然得到我软件的回复。

2 个答案:

答案 0 :(得分:3)

添加这些行也可以阅读StandardError stream

psi.Arguments = "start-server";
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;

call = Process.Start(psi);
call.OutputDataReceived += new DataReceivedEventHandler(call_OutputDataReceived);
call.ErrorDataReceived += new DataReceivedEventHandler(call_OutputDataReceived);
call.Exited += new EventHandler(call_Exited);

call.EnableRaisingEvents = true;

call.BeginOutputReadLine();
call.BeginErrorReadLine();
call.StandardInput.Close();

call.WaitForExit();

return outData.ToString();

答案 1 :(得分:3)

WaitForExit()仅等待进程退出。它不会等待你的进程接收所有输出,所以你有一个竞争条件。

将使用call_OutputDataReceived调用

e.Data == null来表示输出的结束。在使用outData.ToString()之前,您需要等待该通话。

例如,您可以使用new CountdownEvent(2)等待两个流的结束:

    CountdownEvent countdownEvent;

    public string devicesPlus()
    {
        psi.Arguments = "start-server";
        countdownEvent = new CountdownEvent(2);
        call = Process.Start(psi);
        call.OutputDataReceived += new DataReceivedEventHandler(call_OutputDataReceived);
        call.ErrorDataReceived += new DataReceivedEventHandler(call_OutputDataReceived);
        call.EnableRaisingEvents = true;
        call.Exited += new EventHandler(call_Exited);
        call.Start();
        call.BeginOutputReadLine();
        call.BeginErrorReadLine();
        call.StandardInput.Close();
        call.WaitForExit();
        countdownEvent.Wait();
        return outData.ToString();
    }

    private void call_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        if (e.Data != null)
        {
            // prevent race condition when data is received form stdout and stderr at the same time
            lock (outData)
            {
                outData.Append(e.Data);
            }
        }
        else
        {
            // end of stream
            countdownEvent.AddCount();
        }
    }