当使用Sox并推送到stdout时,进程挂起在WaitForExit上



我通过调用c#程序中的进程来使用sox。我知道挂在WaitForExit或Start方法上很流行,但我无法处理它

using (Process process = new Process())
{
    process.StartInfo.FileName = _soxExePath;
    process.StartInfo.Arguments = _task.Arguments.RemoveFirstOccurence("sox");
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();
    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
    {
        process.OutputDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        };
        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
        if (process.WaitForExit(timeout) &&
            outputWaitHandle.WaitOne(timeout) &&
            errorWaitHandle.WaitOne(timeout))
        {
            result = process.ExitCode == 0;
        }
        else
        {
            // Timed out.
        }
    }
}

正如您所看到的,标准输出是异步处理的,但程序仍然挂在WaitForExit上(即使超时设置为100000)。当我在Windows中键入完全相同的命令时,cmd处理所需时间不到一秒钟,所以这不是什么大操作。

sox --combine mix 1.wav 2.wav 3.wav -p | sox - --combine concatenate 4.wav output.wav << causing problem

我知道这是由Sox创建第一个stdout操作引起的。当我尝试一些立即保存到文件的命令时,没有问题。

sox --combine mix 1.wav 2.wav 3.wav output.wav << no problem

答案在于如何调用sox。我猜你也没有完全得到预期的结果。

 process.StartInfo.FileName = _soxExePath;
 process.StartInfo.Arguments = _task.Arguments.RemoveFirstOccurence("sox");
 process.StartInfo.UseShellExecute = false;
 process.StartInfo.RedirectStandardOutput = true;
 process.StartInfo.RedirectStandardError = true;
 process.EnableRaisingEvents = true;
  //<set event handlers here>
 process.Exited += // define what to do to clear up
 process.Start();

有两个区别,一个是启用引发事件来发送和接收任何输出和输入,你只需要设置接收的输出数据,你似乎没有向它发送新的东西。此外,通过倾听出口,你可以处理一切结束的事实。。而不是挂起你的应用程序希望听到它完成。。

我的解决方案就在这里,只需将cmd作为进程调用,并将可执行文件的路径和sox的参数作为进程参数传递。

最新更新