C#流程DataReceivedEventHandler仅工作一次

时间:2018-08-31 18:21:27

标签: c# .net multithreading unity3d process

我有一个Unity应用程序,该应用程序创建一个尝试通过adb shell向Android设备发送命令的进程。我可以在应用程序过程中发送命令。但是我只在第一次收到来自Android设备的输出。我不知道它的OutputDataReceived是否存在缓冲区问题。输入通过,但在Unity编辑器上没有收到任何日志。如果将Process.StartInfo.CreateNoWindow设置为true,则可以看到在Unity外部生成的adb shell中的所有输出。第一次执行后,输出不会从该控制台重定向到Unity。

    public void StartShellProcessAsync ()
    {
        ShellThread = new Thread(() =>
        {
            ShellProcess = new Process();
            ShellProcess.StartInfo.FileName = "adb.exe";
            ShellProcess.StartInfo.Arguments = "shell";

            ShellProcess.StartInfo.CreateNoWindow = false;
            ShellProcess.StartInfo.UseShellExecute = false;

            ShellProcess.StartInfo.RedirectStandardOutput = true;
            ShellProcess.StartInfo.RedirectStandardError = true;
            ShellProcess.StartInfo.RedirectStandardInput = true;

            ShellProcess.EnableRaisingEvents = true;
            ShellProcess.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
            ShellProcess.ErrorDataReceived += new DataReceivedEventHandler(OnErrorDataReceived);

            ShellProcess.Exited += new EventHandler(OnProcessExited);

            ShellProcess.Start();
            ShellProcess.BeginOutputReadLine();
            ShellProcess.BeginErrorReadLine();
            ShellProcess.WaitForExit();
        });
        ShellThread.Start();
    }

我在Unity中有一些按钮可以发送如下命令:

am start -m <application activity>
am stack list

我正在尝试读取am stack list的输出,如果它是我发出的第一个命令,则该输出有效。但是,如果我在am start -m <application activity>之后运行它,则输出不会传递到Unity。

之所以在线程内运行ShellProcess是为了使该进程在应用程序的整个执行过程中保持打开状态。我不想为我发送给Android的每个命令都耗时而产生新的过程。

1 个答案:

答案 0 :(得分:0)

尝试锁定您的线程。这样可以确保一次仅激活一个进程。

如果另一个线程正忙于执行相同的进程而又调用了一个新线程,则会出现一些冲突。

private readonly object balanceLock = new object();

//Place this code elsewhere
private void Instantiate_Shell_Once()
{

        ShellProcess = new Process();
        ShellProcess.StartInfo.FileName = "adb.exe";
        ShellProcess.StartInfo.Arguments = "shell";

        ShellProcess.StartInfo.CreateNoWindow = false;
        ShellProcess.StartInfo.UseShellExecute = false;

        ShellProcess.StartInfo.RedirectStandardOutput = true;
        ShellProcess.StartInfo.RedirectStandardError = true;
        ShellProcess.StartInfo.RedirectStandardInput = true;

        ShellProcess.EnableRaisingEvents = true;
        ShellProcess.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
        ShellProcess.ErrorDataReceived += new DataReceivedEventHandler(OnErrorDataReceived);

        ShellProcess.Exited += new EventHandler(OnProcessExited);

}

public void StartShellProcessAsync ()
{
    ShellThread = new Thread(() =>
    {
        lock(balanceLock)
        {

        ShellProcess.Start();
        ShellProcess.BeginOutputReadLine();
        ShellProcess.BeginErrorReadLine();
        ShellProcess.WaitForExit();

       }
   });
   ShellThread.Start();
}