Task.Factory.StartNew在ASP.Net MVC中有帮助或有害吗?

时间:2014-06-23 08:42:43

标签: asp.net asp.net-mvc task threadpool

我有一个需要发出多个Web请求的MVC控制器操作。因此,为了尝试释放此线程来处理其他传入的Web请求,我写了这样的东西: (注意:这是对实际代码的过度简化)

public async Task<ViewResult> Index()
{
   MyObj o = await Task.Factory.StartNew<MyObj>(() =>
   {
      WebClient c = new WebClient();
      var res1 = c.DownloadString("...");
      var res2 = c.DownloadString("..."); //Not shown but res1 required for this call.
      return new MyObj(res1, res2);
   }
   return View(o);
}

我的问题是,通过启动新线程来完成这项工作,我做得更好或更糟。我的目的是释放这个.Net线程来处理网络请求时的其他传入请求。但看了之后我觉得我还在制作一个.Net线程块,只是可能与线程池不同而不是原始块,所以我真的没有好转。那么我的怀疑是否正确以及上述代码使事情变得更糟?

Task.Factory.StartNew()的好处如果有效......就是它简化了必须完成所有异步的内部工作。我的问题是:这样做是否实际上是一个线程来处理传入的Web请求,还是它仍然从线程池中占用相同数量的线程?

3 个答案:

答案 0 :(得分:4)

是的,你现在正在阻止另一个线程。

如果这很好,MVC会自动将所有动作方法包装在新任务中。

要取消阻止线程,您需要在封面下的某个位置使用异步IO。 BCL通常提供这个。如果它说&#34; async&#34;在盒子上它通常是异步IO。

也就是说,很少有网络应用程序存在线程耗尽的问题。如有必要,线程池会启动大量线程。根据可用线程数量,很少有Web应用程序的吞吐量受限。你真的需要处理100个并发请求吗?您的后端服务甚至可以处理此负载吗?如果这些问题中的任何一个被#34; no&#34;你不需要异步。

答案 1 :(得分:2)

您所制作的代码并不是最佳,因为两个长操作都会相互阻塞:

var result1 = c.DownloadString("...");

将首先运行,完成后运行

var result2 = c.DownloadString("...");

在其中运行的额外线程不会提高性能,也不会释放任何打开的请求。

答案 2 :(得分:1)

你不需要工厂。您可以将示例简化为:

public async Task<ViewResult> Index()
{
    WebClient client = new WebClient();
    var result1 = await client.DownloadStringAsync("...");
    var result2 = await client.DownloadStringAsync("...");

    /* whatever you're doing with result1 & result2 */     

   return View();
}