как запустить процесс после завершения другого асинхронного процесса (независимый от веб-запроса) - PullRequest
0 голосов
/ 17 января 2019

Я работаю над API для конвертации видео. пользователи будут загружать свои видео, API преобразует их (с помощью ffmpeg) и затем сохраняет их. Я вызываю метод преобразования из моего контроллера. Вот как выглядит метод преобразования:

var arguments = "-i " + inputDir + " -c:v libx264 -preset fast -crf 25 -r 23.976 -ar 44100 -ac 2 -c:a aac -strict -2 -b:a 112k " + outputDir;

var process = new Process()
{
    StartInfo = new ProcessStartInfo()
    {
        UseShellExecute = false,
        FileName = ffmpegDir,
        CreateNoWindow = true,
        Arguments = arguments
    },
    EnableRaisingEvents = true
};
process.Start();
process.Exited += (sender, args) =>
{
    //store the output file
};  

Когда я развернул его в производство, у меня возникли серьезные проблемы. Если один клиент загружает свое видео, проблем нет. но если несколько клиентов пытаются загрузить свои видео одновременно, приложение перестает отвечать на запросы. Я знаю, что процесс преобразования видео занимает много ресурсов процессора, поэтому, если начинается многократное преобразование, то сервер зависает.

Я придумал архитектуру для решения, но я не знаю, как я могу это реализовать. Это моя идея

  1. Мне нужно запустить процесс преобразования в новом потоке, чтобы он полностью отличался от основного потока. 1 поток / процесс за раз, независимо от количества веб-запросов.
  2. Когда новый поток пытается запустить процесс, он проверяет, есть ли уже запущенный предыдущий поток / процесс или нет. если да, то поток будет приостановлен, а если нет, то поток начнется.
  3. После завершения какого-либо потока он проверит, есть ли ожидающие потоки или нет, затем повторите процедуру с шага 2.

Каков наилучший способ сделать это? Как я могу отслеживать, есть ли какие-либо потоки / процессы, уже запущенные в фоновом режиме?

1 Ответ

0 голосов
/ 17 января 2019

Вы можете создать специальный поток, который начнет новый процесс. Затем добавьте очередь для связи с этим потоком

псевдокод:

public class ApiController
{
  private Queue<string> queue = new Queue<string>();
  private object sync = new object();

  public ApiController()
  {
    // create a thread here or on web app start
  }

  private void ThreadProc()
  {
    while (true)
    {
      string filename = null;
      lock (sync)
      {
        if (queue.Count() > 0)
          filename = queue.Dequeue();
      }

      if (filename != null)
      {
        // create process
      }
      else
      {
        Thread.Sleep(100);
        continue;
      }
    }
  }

  public void ApiMethod()
  {
    // save file from request stream and pass name of this file to thread
    string filename = ...
    lock (sync)
      queue.Enqueue(filename);
  }
}

Этот подход позволяет вам иметь только один запущенный процесс в любое время

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...