如何在另一个异步进程结束后启动一个进程(与Web请求无关)

时间:2019-01-17 12:22:11

标签: c# multithreading process

我正在开发视频转换Web 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
};  

当我将其部署到生产环境中时,我遇到了一些严重的问题。如果有一个客户上传他的视频,那就没有问题。但是如果多个客户端尝试同时上传他们的视频,则该应用程序将无响应。我知道视频转换过程需要大量的CPU资源,这就是为什么如果开始多次转换会导致服务器挂断的原因。

我想出了一种解决方案的体系结构,但我不知道如何实现。这是我的主意

  1. 我必须在新线程中运行转换过程,以便它与主线程完全不同。一次有1个线程/进程,无论那里有多少个Web请求。
  2. 当新线程尝试运行进程时,它将检查是否有任何先前的线程/进程已经在运行。如果是,则线程将暂停,如果否,则线程将启动。
  3. 任何线程结束后,它将检查是否有任何挂起的线程,然后从步骤2开始重复。

最好的方法是什么?我如何跟踪后台是否已在运行任何线程/进程?

1 个答案:

答案 0 :(得分:1)

您可以创建一个专用线程来启动新进程。然后添加一个队列以与该线程通信

伪代码:

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

这种方法允许您在任何时候只有一个正在运行的进程