3 Stimmen

Verwendung der Task Parallel Library (C# .NET 4.0) mit einer externen Exe (ffmpeg) ohne Konflikte

Ich versuche schon seit einigen Tagen, ein Problem zu lösen. Ich bin ein Anfänger im Bereich Multithreading. Mein Ziel ist es, mehrere Videokodierungsaufgaben gleichzeitig auszuführen, indem ich ffmpeg.exe und die gesamte Leistung des Servers zu nutzen.

Ich habe einen C#-Wrapper, der die ffmpeg.exe Prozess und funktioniert ohne Threading (oder nur mit ffmpeg-internem Threading (nicht verfügbar für die flv-Kodierung)), was wie folgt aussieht:

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;
}

Der folgende Code ruft den Wrapper auf. Der zweite Parameter eines jeden Encode Methode ist die Anzahl der Threads, die für das interne ffmpeg-Threading verwendet werden sollen. Wenn ich es deaktiviere, funktioniert es nicht.

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);

Sie fragen sich wahrscheinlich, warum ich ein Timeout von 5000 für WaitAll() . Das liegt daran, dass der aufrufende Thread auf unbestimmte Zeit wartet, weil TPL kein Ende der Aufgaben erkennt. ffmpeg.exe Prozesse "stoppen" in der Mitte der Kodierung und laufen mit 0% der CPU weiter.

Ich denke, TPL und Process sind widersprüchlich. Wenn ich den Status der einzelnen Aufgaben mit TPL abrufe, bleibt er die ganze Zeit über "Running". Ich möchte die tatsächlichen Ereignisse von ffmpeg-Prozessen mit TPL (oder einem anderen Mechanismus) erfassen, weil ich verhindern möchte, dass die Anwendung abstürzt, und Erfolge und Misserfolge verwalten möchte.

0voto

Kit Punkte 16901

Ich bezweifle, dass das Problem bei TPL oder bei einem selbst entwickelten Mechanismus liegt, mit dem festgestellt wird, ob der Prozess endet. Ich vermute, der wahre Grund ist, dass die Wartezeit nicht unendlich ist, sondern ein klassischer Fall von Thrashing aufgrund von Druck auf eine bestimmte Ressource.

In Anbetracht Ihrer Beschreibung des Geschehens und der Tatsache, dass die CPU auf niedrigem Niveau zu sein scheint, liegt der Druck wahrscheinlich bei IO oder Speicher. Ich schlage vor, ein Profil Ihrer Anwendung mit Hilfe von Leistungszählern zu erstellen (und den Task-Manager als schnellen Blick auf die Oberfläche zu verwenden), um herauszufinden, was los ist.

Wie ein Kommentator vorschlug, ist es sinnvoll, die Aufgabenstellung zu eliminieren und festzustellen, ob ein, zwei oder mehrere serielle Aufrufe zur Kodierung zumindest funktionieren. Es kann sein, dass ein bestimmter Aufruf alles aufhält (z. B. ein Kodierungsfehler) und nicht ein Ressourcenproblem.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X