3

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,我会突然从我的软件中得到回复。

4

2 回答 2

4

WaitForExit()只等待进程退出。它不会等待您的进程接收所有输出,因此您在那里有一个竞争条件。

call_OutputDataReceived将被调用e.Data == null以表示输出的结束。在使用之前,您需要等待该呼叫outData.ToString()

例如,您可以使用 anew 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();
        }
    }
于 2013-05-11T10:22:10.423 回答
3

添加这些行以读取StandardError 流

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();
于 2013-05-11T09:37:00.733 回答