Использование библиотеки параллельных задач (C# .NET 4.0) с внешним исполняемым файлом (ffmpeg) без конфликтов

Уже несколько дней пытаюсь решить проблему. Я новичок в многопоточности. Моя цель — запустить несколько задач кодирования видео одновременно с помощью ffmpeg.exe и использовать всю мощь сервера.

У меня есть оболочка С#, которая запускает процесс ffmpeg.exe и работает без потоковой передачи (или только с внутренней потоковой передачей ffmpeg (недоступной для кодирования flv)), которая выглядит следующим образом:

using (Process process = new Process())
{
    process.StartInfo.FileName = encoderPath + "ffmpeg.exe";

    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.CreateNoWindow = false;

    string arguments = "-y -i " + filenameInput + " -f " + 
        GetVideoFormatName(format) + " -vcodec " + GetVideoCodecName(codec);

    // (most argument setup has been omitted for brevity)
    arguments += " " + filenameOutput + " ";

    process.StartInfo.Arguments = arguments;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.Start();

    bool succes = LireSortie(process);
    process.WaitForExit();
    process.Close();
    return succes;
}

В приведенном ниже коде вызывается оболочка. Второй параметр каждого метода Encode — это количество потоков, используемых для внутренней обработки потоков ffmpeg. Когда я отключаю его, он не работает.

var fm = new FFMpegWrapper();

fm.FilenameInput = "test.mp4";
//VideoInfo videoinfo = fm.GetVideoInfo();
Task[] tasks = {
    Task.Factory.StartNew(
        new Action(()=>{ fm.Encodeto200p("test200p.mp4", 4); })),
    Task.Factory.StartNew(
        new Action(()=>{ fm.EncodetoFlash200p("test200p.flv"); })),
    // ... (calls to other Encode methods ommitted) ...
    Task.Factory.StartNew(
        new Action(()=>{ fm.Encodeto404p("test404p.mp4", 4); })),
    Task.Factory.StartNew(
        new Action(()=>{ fm.EncodetoFlash404p("test404p.flv"); })),
    Task.Factory.StartNew(
        new Action(()=>{ fm.Encodeto720p("test720p.mp4", 4); }))
};

Task.WaitAll(tasks, 5000);

Вам, наверное, интересно, почему я поставил тайм-аут 5000 для WaitAll(). Это связано с тем, что вызывающий поток ожидает бесконечно долго, потому что TPL не обнаруживает окончания задач. ffmpeg.exe процессы "останавливаются" в середине кодирования и продолжают работать с 0% загрузки ЦП.

Я думаю, что TPL и Process конфликтуют. Когда я получаю статус каждой задачи с помощью TPL, она все время остается «Выполняется». Я хотел бы фиксировать реальные события процессов ffmpeg с помощью TPL (или какого-либо другого механизма), потому что я хочу предотвратить сбой приложения и хочу управлять успехами и неудачами.


person LSMetag    schedule 20.12.2010    source источник
comment
Заканчиваются ли процессы ffmpeg? то есть, если вы запустили тот же код без задачи вокруг него, он завершается?   -  person Arne Claassen    schedule 27.08.2011
comment
Так что проблема не имеет ничего общего с TPL. Проблема в том, что ffmpeg не закрывается. Правильный?   -  person usr    schedule 29.05.2012


Ответы (1)


Я сомневаюсь, что проблема связана с TPL или с каким-либо доморощенным механизмом, используемым для определения завершения процесса. Подозреваю, что настоящая причина в том, что ожидание не бесконечное, а классический случай пробуксовки из-за нагрузки на тот или иной ресурс.

Учитывая ваше описание того, что происходит, и то, что ЦП, похоже, находится на низком уровне, ваша нагрузка, вероятно, связана с вводом-выводом или памятью. Я предлагаю профилировать ваше приложение как минимум с помощью счетчиков производительности (и использовать диспетчер задач для быстрого просмотра поверхностного уровня), чтобы выяснить, что происходит.

Как предположил комментатор, имеет смысл исключить постановку задач и определить, работают ли хотя бы один, два или более последовательных вызовов для кодирования. Может случиться так, что один конкретный вызов задерживает все (например, ошибка кодирования), а не проблема с ресурсами.

person Kit    schedule 07.06.2012