在这个ASP.NET .ashx代码片段中使用Task.Factory.StartNew <action>()有什么好处吗?</action>

时间:2015-03-31 18:13:31

标签: c# asp.net multithreading async-await task-parallel-library

这是一个.ashx处理程序,它创建一系列Task对象,然后在foreach循环中执行。

        List<Task<Action>> list = new List<Task<Action>>();

        list.Add(Task.Factory.StartNew<Action>(() => AddHeader(graphics, request, reportParameters)));
        list.Add(Task.Factory.StartNew<Action>(() => AddSubmitter (graphics, request, reportParameters)));
        list.Add(Task.Factory.StartNew<Action>(() => AddActivity(graphics, request, reportParameters)));
        list.Add(Task.Factory.StartNew<Action>(() => AddCharts(graphics, request, reportParameters)));

        //Task.WaitAll(list.ToArray()); //AY - This seems unnecessary
        foreach (var action in list.Select(t => t.Result))
        {
            action();
        }

返回Action的每个方法都会执行CPU密集型工作,如下面的第一个方法。

private Action AddHeader(XGraphics graphics, HttpRequest request, ReportParameters reportParameters)
    {
        DataSet ds = new myData().ClientHeader(reportParameters);

        // This will be a function waiting to be called.
        return () =>
        {
          // Some CPU intensive operation code here.
        };
    }

有人可以帮我理解这段代码是否有用 1)从异步或多任务角度来看? 2)此代码是否甚至从ASP.NET线程池创建多个线程?

当我调试应用程序时,它在运行foreach循环之前在我的机器上显示4个单独的任务。每个任务都会检索数据集,我认为这是因为每个方法中的部分代码都在return()Action语句之前运行。

此代码的全部目的是在执行每个CPU密集型操作方法之前在单独的任务中启用多个数据库调用吗?或者代码真的在做异步的东西吗?

1 个答案:

答案 0 :(得分:1)

这不是利用代表线程池执行单元的任务的最佳方式:

  1. 因为每个此类任务都将阻塞线程池中的一个线程,并且ASP.NET使用the same thread pool作为任务,所以您将并发请求数量减少五倍。
  2. 利用数据库(I / O)绑定代码is ineffective的线程池线程,因为线程池线程只是空闲,所以使用async code进行数据库调用。
  3. 但这不是最后一个问题 - foreach (var action in list.Select(t => t.Result))将阻止执行,直到它从每个任务顺序获得Result。这意味着返回的操作一旦准备执行就不会被执行,它们将按照添加到列表中的顺序执行,否则如果我们一旦执行它们就可能获得的任何潜在优势准备好了。
  4. 所以,作为结论:

    这样的代码只是以资源效率最低的方式启动了4个数据库调用,然后浪费了4个错误使用的线程池线程来执行它们的&#34; continuation&#34;原始线程中的顺序没有利用4任务可以按任意顺序执行的可能性。

    P.S。:即使您真的需要进行CPU密集型处理,也不要使用Factory.StartNew - 使用Task.Run。这不是实际错误,因为它们基本上做同样的事情,而是a good recommendation