1

我需要在 MVC 3 应用程序中进行一些音频处理,并且想知道这些不同背景方法的优缺点。作为一般规则,音频处理将是一个长时间运行的过程,所以我只想确保 IIS 可以自由处理其他请求。

  1. AsyncController & 后台工作者

    public ActionResult GetAudioCompleted(byte[] audio)
    {
    return File(audio, "audio/wav", "mywavfile.wav");
    }
    
    public void GetAudioAsync()
    {          
        BackgroundWorker w = new BackgroundWorker();
        w.RunWorkerCompleted += (s, e) =>
        {
            AsyncManager.Parameters["audio"] = e.Result;
            AsyncManager.OutstandingOperations.Decrement();
        };
        w.DoWork += (s, e) =>
        {      
            byte[] b;       
            using (var ms = new MemoryStream())
            {
                // Process audio to memory stream
    
                ms.Seek(0, SeekOrigin.Begin);
                b = new byte[ms.Length];
                ms.Read(b, 0, (int)ms.Length);
                e.Result = b;
            }
        };
        AsyncManager.OutstandingOperations.Increment();
        w.RunWorkerAsync();            
    }
    
  2. 异步控制器和任务

    public ActionResult GetAudioCompleted(byte[] audio)
    {
        return File(audio, "audio/wav", "mywavfile.wav");
    }
    
    public void GetAudioAsync()
    {            
        AsyncManager.OutstandingOperations.Increment();
        var t = Task<byte[]>.Factory.StartNew(() =>
        {
            byte[] b;
            using (var ms = new MemoryStream())
            {
                // Process audio to memory stream
                ms.Seek(0, SeekOrigin.Begin);
                b = new byte[ms.Length];
                ms.Read(b, 0, (int)ms.Length);
            }
            return b;
        })
        .ContinueWith(c =>
            {
                AsyncManager.Parameters["audio"] = c.Result;
                AsyncManager.OutstandingOperations.Decrement();
            });          
    }
    
  3. 非异步控制器和线程

    public ActionResult GetaAudio()
    {
        byte[] b;
    
        using (var ms = new MemoryStream())
        {
            var t = Thread(() =>
                {
                    // Process audio to memory stream
                });
            t.Start();
            t.Join();
    
            // error checking etc.
            ms.Seek(0, SeekOrigin.Begin);
            b = new byte[ms.Length];
            ms.Read(b, 0, (int)ms.Length);
            return File(b, "audio/wav", "mywavfile.wav");
        }
    }
    

问题:

  1. 是否推荐将 BackgroundWorkers 用于 Web 应用程序?
  2. 如果我使用任务,这个后台线程是否使用 IIS 线程池中的一个(可能会否定这种方法的好处之一,因为线程没有被释放用于请求处理)?
  3. 使用 System.Threading.Thread - 此线程是否使用 IIS 线程池中的一个。t.Join() 会阻塞当前的 IIS 线程吗?

哪种方法对您来说似乎更好,为什么?欢迎任何其他方法。

4

1 回答 1

2
  1. 不会。ASP.NET 和 IIS 在自己的线程上执行每个 HTTP 请求/响应。ASP.NET 中的异步编程更多的是为每个请求做更多的工作(例如在单独的线程上执行不相关的 SQL 查询),而不是处理线程化请求。

  2. 我不知道,我对Tasks不太熟悉。

  3. 是的,是的。

我会这样做(伪代码):

  1. 我会处理文件,然后在后台线程中处理它(使用简单的System.Threading.Thread实例),这意味着 IIS 请求/响应线程不会被阻止并且可以立即将 HTML 返回给客户端。
  2. 我会在某处存储此文件处理作业的令牌或引用。然后我会将 303 重定向返回到“/processingJobs/job123”(其中 job123 是作业 ID)。
  3. actionHandler forGET processingJobs将查找作业 123 的后台线程并查看它是否已完成,如果未完成,则返回 HTML 响应“正在处理您的作业,请再次刷新页面以获取更新状态”,以及每 5-10 秒刷新一次页面的小 javascript。
  4. 如果作业完成,则返回已处理的带有content-disposition:标题的音频文件。

如果音频处理由单独的进程或队列系统处理,而不是同时处理所有这些,则这种技术可以很好地扩展,甚至可以无限扩展。

一般准则:如果无法在 100 毫秒内完成 HTTP 请求/响应,则在后台执行工作并立即返回状态消息。

于 2013-03-07T03:03:23.433 回答