c# – ASP.Net页面或Async页面中可接受的基于任务的编程是首选方法

我在不是异步页面的页面中使用以下基于任务的编程(TPL).

我的问题是:使用TPL(即任务并行库)在ASP.Net页面中创建多线程调用是否可以,或者必须始终在ASP.Net页面中使用内置的异步页面功能进行多线程处理?到目前为止,TPL方法没有产生任何问题,但只是想确保我在ASP.Net页面中使用TPL时遗漏了一些重要的点/隐藏风险.

       Task.Factory.StartNew(() =>
                {
                    try
                    {
                        Method1(); 
                        success4 = true;
                    }
                    catch (Exception e4)
                    {
                        success4 = false;
                        ex = e4.ToString();
                    }
                }),
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        Method2();
                        success5 = true;
                    }
                    catch (Exception e5)
                    {
                        success5 = false;
                        ex = e5.ToString();
                    }
                }),
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        Method3();
                        success6 = true;
                    }
                    catch (Exception e6)
                    {
                        success6 = false;
                        ex = e6.ToString();
                    }
                })
            };
   Task.WaitAll(tasks);

更新1:

正如在答案中指出的那样,在ASP.Net中使用TPL会限制ASP.Net应用程序的可伸缩性,因为每个任务都使用来自ASP.Net线程池的线程,同时保持页面的原始线程在封锁状态.
我正在考虑在Async页面中调用方法时使用TPL,如下面的代码所示,以利用并行性带来的更强大的处理.但我会进一步研究这一点,看看在实际情况下,TPL是否会使异步方法更好或更差.

private void DoTask4(object[] paras)
    {
        Parallel.Invoke(() =>
            {
               try
               {
                   Method4( paras);
               }
               catch (Exception e4)
               {
                   success4 = false;
                   //log the exception
               }
           });
    }

    IAsyncResult BeginAsyncOperation4(object sender, EventArgs e, AsyncCallback cb, object state)
    {
        task4 = new AsyncTaskDelegate(DoTask4);
        IAsyncResult result = task4.BeginInvoke(state as object[], cb, "task4");
        return result;
    }

    void EndAsyncOperation4(IAsyncResult ar)
    {
        task4.EndInvoke(ar);
        if (success4 == null)
        {
            success4 = true;
        }
    }

    void TimeoutAsyncOperation4(IAsyncResult ar)
    {
        success4 = false;
    }

更新2:

最后,正如答案中所指出的,即使使用TPL和Async页面方法也会导致线程池中的线程被使用,这再次意味着我们的ASP.Net可伸缩性将成为一个问题.
因此,最好不要在Async页面中使用TPL.

最佳答案 这种方法可能严重损害服务器的可伸缩性,因为它使用额外的theads并阻塞请求线程.假设Method1..3负责一些IO绑定工作.如果您不能使用异步ASP.NET控制器,您仍然可以使用AsyncManager(例如,像
this)或
PageAsyncTask(对于经典ASP.NET)启动异步IO绑定操作并避免阻塞.

但是,如果你需要做一些CPU绑定工作(而不是IO绑定工作),只需在同一个请求线程上,一步一步,而不是并行执行.否则,每个Task.Factory.StartNew可能会暂停另一个传入的HTTP请求,具体取决于服务器负载.因为您可能希望尽可能多地提供并发HTTP请求,所以应避免并行化CPU绑定工作.

也就是说,您的代码可能适用于并发HTTP请求数较少的Intranet Web应用程序.如果您想加快单个请求的响应传递,则可以这样做.

点赞