2010-09-25 74 views
6

我想在我的ASP净MVC应用程序中实现这样的逻辑:ASP.NET MVC多线程

user clicks a button - >

server executes some time-consuming logic in ~15 threads (i get data from really slow independent sources) - >

when all work is done, server merges the results and passes it back to user 

有一天,我看到一篇文章解释了为什么在asp-net应用程序中创建新的线程是高度不推荐的,并且ThreadPool是应该使用的。 这种情况下mvc的最佳做法是什么?为什么我不应该创建自己的线程,背景工作者,任务,并使用线程池?如果有问题,该应用程序将托管在公共服务器上。

回答

4

如果您使用.Net 4,我甚至会建议查看并行命名空间。他们使这更简单,并更好地利用所有CPU核心。

我也会看看从你的主要web应用程序卸载这一切。拥有一组单独的服务或消息队列来处理这个长时间运行的请求,可以让您更轻松地进行扩展,并允许您的Web应用程序担心服务页面请求,而不是执行长时间运行的逻辑。谷歌起来像“iis长期运行请求”开始。

3

因为一个线程池的设计做到这一点:

它提供了可用于执行任务,岗位工作项目线程池,处理异步I/O,等待代表其他线程,和处理计时器。

我想最好是在服务器完成时将结果存储在数据库中。

然后你可以使用一个定时器和AJAX,如果制造工艺,以周期性地请求,如果是的话,得到的数据。

3

你不应该创建自己的线程,因为这有显著的开销。创建一个新线程很昂贵。所以问题应该是:为什么你不应该使用线程池?它有许多线程可供使用。更好的方法是使用任务并行库,它在线程池上方提供了一个抽象层,使得使用线程更容易。

你应该认识到,唯一的(简单)的方式来做到这一点,是直到所有工作完成,然后服务页面让用户等待。更复杂但更具响应性的方法是使用Ajax(例如通过jQuery)定期询问服务器工作进展的程度。这样你也可以提供一些进度指标。

+0

这将是一个由管理员/主持人执行的操作,所以它不是那种吝啬的:) – 2010-09-25 17:53:18

6

是jQuery和一些AJAX会做最正确的。 加载页面,然后发送〜15个不同的Ajax查询返回到服务器,让他们完成异步。这样,您可以让Web服务器处理线程(这很好),并专注于在等待时向用户显示代码或虚拟进度条。

+2

只要工作可以按这种方式分解,那么这是一个非常好的方法...除了避免陷入自己的陷阱线程,在用户反馈过程中提供反馈会更容易。 – 2010-09-25 17:57:33

+2

这是否是一种好方法取决于您是要合并服务器上还是客户端上的结果。存在风险,您需要将大量逻辑移动到客户端,以便在服务器上更好地处理。 – 2010-09-25 19:13:35

+0

这看起来像是一个简单的修复,但如果您的客户在不同的标签中打开了相同的URL,您将很快注意到每个浏览器打开连接到单个域的限制。 (很多人现在用websockets发现的东西)与Jim Leonardo提出的相比,你的服务器可以处理的请求数量减少到1/15。 Rohan Singh的答案不那么复杂,只比Jim的 – Cohen 2013-01-22 13:32:22

7

这似乎是一个非常好的地方在ASP.NET MVC 2中使用新的AsycController。它非常易于使用,并允许您在不阻止请求线程的情况下针对多个独立源运行查询。

MSDN has a great example他们在哪里查询新闻服务,天气服务和体育服务。

您可以在它们被查询每个源依次原来代码中看到,但在最终版本中,所有的任务并行和控制返回到控制器上运行时,他们都完成了:

public void IndexAsync(string city) 
{ 
    AsyncManager.OutstandingOperations.Increment(3); 

    NewsService newsService = new NewsService(); 
    newsService.GetHeadlinesCompleted += (sender, e) => 
    { 
     AsyncManager.Parameters["headlines"] = e.Value; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 
    newsService.GetHeadlinesAsync(); 

    SportsService sportsService = new SportsService(); 
    sportsService.GetScoresCompleted += (sender, e) => 
    { 
     AsyncManager.Parameters["scores"] = e.Value; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 
    sportsService.GetScoresAsync(); 

    WeatherService weatherService = new WeatherService(); 
    weatherService.GetForecastCompleted += (sender, e) => 
    { 
     AsyncManager.Parameters["forecast"] = e.Value; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 
    weatherService.GetForecastAsync(); 
} 

public ActionResult IndexCompleted(string[] headlines, string[] scores, string[] forecast) 
{ 
    return View("Common", new PortalViewModel { 
     NewsHeadlines = headlines, 
     SportsScores = scores, 
     Weather = forecast 
    }); 
} 
+0

稍微小一点这个链接现在被破坏 – PandaWood 2012-10-24 23:53:19

+0

该死的,一个URL应该是一个承诺,特别是在文档等方面。同样令人讨厌的是,URL只是变化不大(添加“(vs = v.100)”并不明显)。无论如何,谢谢你指出,@PandaWood。现在修复。 – 2012-10-28 00:17:54

+0

由于MVC 4+控制器包含异步功能,现在这已过时。这里有一个例子:http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4 – 2015-01-05 15:34:39