C# 如何确定FFmpeg过程何时完成

C# 如何确定FFmpeg过程何时完成,c#,.net,audio,ffmpeg,C#,.net,Audio,Ffmpeg,删除文件时,经常(可能80%的时间)引发以下异常: IOException:进程无法访问文件“C:\MyOriginalFile.webm”,因为其他进程正在使用该文件 创建和运行FFmpeg进程的调用如下所示: var origFilePath = "C:/MyOriginalFile.webm"; var processedFilePath = "C:/MyProcessedFile.webm"; RunFfmpeg($"-i \"{origFilePath}\" -af \"silenc

删除文件时,经常(可能80%的时间)引发以下异常:

IOException:进程无法访问文件“C:\MyOriginalFile.webm”,因为其他进程正在使用该文件

创建和运行FFmpeg进程的调用如下所示:

var origFilePath = "C:/MyOriginalFile.webm";
var processedFilePath = "C:/MyProcessedFile.webm";

RunFfmpeg($"-i \"{origFilePath}\" -af \"silenceremove=1:0.1:0.001, areverse, silenceremove=1:0.1:0.001, areverse\" \"{processedFilePath}\" -y");

// fails with IOException as the file presumably not been released by FFmpeg
System.IO.File.Delete(origFilePath);
私有列表RunFfmpeg(字符串参数)
{
使用(var进程=新进程())
{
process.StartInfo.RedirectStandardOutput=true;
process.StartInfo.RedirectStandardError=true;
process.StartInfo.FileName=\u hostingEnvironment.ContentRootPath+\u settings.FfmpegPath;
process.StartInfo.Arguments=参数;
process.StartInfo.UseShellExecute=false;
process.StartInfo.CreateNoWindow=true;
//ffmpeg仅将strerr用于其输出
var输出=新列表();
process.ErrorDataReceived+=新的DataReceivedEventHandler((s,e)=>{
如果(如数据!=null)
输出。添加(如数据);
});
process.Start();
process.BeginErrorReadLine();
process.WaitForExit();
返回输出;
}
}
看起来,即使删除文件时该过程已完成,FFmpeg仍在处理或未发布该文件


这种行为是预期的吗?在继续之前,如何确保FFmpeg已完成文件处理

如果是我,我会在后台线程上运行此程序,然后点击
进程。退出
事件并尝试删除其中的文件

使用此策略并轮询30秒,直到Exitd事件触发并检查ExitCode。根据ExitCode的不同,您可以给它更多的时间,检查文件是否仍然被锁定,或者执行另一个操作,直到
process.ExitCode==0

private List<string> RunFfmpeg(string arguments)
{
    using (var process = new Process())
    {
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.FileName = _hostingEnvironment.ContentRootPath + _settings.FfmpegPath;
        process.StartInfo.Arguments = arguments;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;

        // ffmpeg only uses strerr for its output
        var output = new List<string>();
        process.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { 
            if (e.Data != null)
                output.Add(e.Data);
        });

        process.Start();
        process.BeginErrorReadLine();
        process.WaitForExit();
        return output;
    }
}

如果是我,我会在后台线程上运行此程序,然后点击
进程。退出
事件并尝试删除其中的文件

使用此策略并轮询30秒,直到Exitd事件触发并检查ExitCode。根据ExitCode的不同,您可以给它更多的时间,检查文件是否仍然被锁定,或者执行另一个操作,直到
process.ExitCode==0

private List<string> RunFfmpeg(string arguments)
{
    using (var process = new Process())
    {
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.FileName = _hostingEnvironment.ContentRootPath + _settings.FfmpegPath;
        process.StartInfo.Arguments = arguments;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;

        // ffmpeg only uses strerr for its output
        var output = new List<string>();
        process.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { 
            if (e.Data != null)
                output.Add(e.Data);
        });

        process.Start();
        process.BeginErrorReadLine();
        process.WaitForExit();
        return output;
    }
}

在删除文件之前,请检查文件是否没有锁定:@JeremyThompson如果文件已锁定怎么办?我希望有一种比Thread.Sleep更优雅的方法来实现这一点。在删除文件之前,检查文件是否没有锁定:@JeremyThompson,那么如果它被锁定呢?我希望有一种比Thread.Sleep更优雅的方法来实现这一点。这是C进程在进程实际完成之前触发退出事件的预期行为吗?不,进程应该退出。如果这不是您看到的行为,也许您应该轮询进程,以100%确定FFMpeg转换已完成。@ajbeaven我发现了导致我提出这个问题的原因。我目前正在进行一次调查。顺便说一下,cehoyo在罚单中的假设是错误的。如果某个流程是由子流程完成的,则该流程在完成后仍然可以“处理”某个内容。我想这就是我的问题所在。你知道如何解决这个问题吗?这是C#进程在进程实际完成之前触发退出事件的预期行为吗?不,进程应该退出。如果这不是您看到的行为,也许您应该轮询进程,以100%确定FFMpeg转换已完成。@ajbeaven我发现了导致我提出这个问题的原因。我目前正在进行一次调查。顺便说一下,cehoyo在罚单中的假设是错误的。如果某个流程是由子流程完成的,则该流程在完成后仍然可以“处理”某个内容。我想这就是我的问题所在。你知道怎么解决那个问题吗?