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_OutputDataReceivede.Data == null出力の終わりを示すために で呼び出されます。を使用する前に、その呼び出しを待つ必要がありますoutData.ToString()

たとえば、 aを使用しnew CountdownEvent(2)て、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 に答える