Ilya Smagin
Ilya Smagin

Reputation: 6152

ASP.NET MVC Multithreading

I want to implement such logic in my asp-net-mvc application:

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

The other day i've seen an article which explained why creating new Threads in asp-net application is highly not recommended, and ThreadPool is the one that should be used. What are best practices for mvc in this case? Why shouldnt i create my threads, backgroundworkers, tasks, whatever by myself and use threadpool? The Application will be hosted on a public server, if it matters.

Upvotes: 7

Views: 11672

Answers (5)

Rohan Singh
Rohan Singh

Reputation: 21535

This seems like a really good place for using the new AsycController in ASP.NET MVC 2. It is really easy to use and lets you run queries against multiple independent sources without blocking request threads.

MSDN has a great example where they are querying a news service, a weather service, and a sports service.

You can see in the original code that they are querying each source sequentially, but in the final version, all the tasks run in parallel and control returns to the controller when they are all completed:

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
    });
}

Upvotes: 7

Jim L
Jim L

Reputation: 2327

If you're using .Net 4, I would even recommend looking at the parallel namespaces. They make this even simpler and do a better job of utilizing all your CPU cores.

I would also look at offloading this from your main web app altogether. Having a separate set of services or a message queue to handle this long running request will let you scale a lot more easily and will allow your web app to worry about servicing page requests, not performing long running logic. Google up something like "iis long running request" to get started.

Upvotes: 4

Rune Baess
Rune Baess

Reputation: 216

Yes JQuery and some AJAX will do it most properly. Load the Page, then send ~15 separate Ajax queries back to the Server and let them finish asynchronously. This way you can let the web-server handle Threading (which is does well) and concentrate on displaying either a ticker or a virtual progress bar to the user while waiting.

Upvotes: 6

Ronald Wildenberg
Ronald Wildenberg

Reputation: 32134

You shouldn't create your own threads because this has significant overhead. Creating a new thread is expensive. So the question should be: why shouldn't you use the threadpool? It has a number of threads ready for use. An even better approach would be to use the task parallel library, it provides a layer of abstraction above the threadpool that makes it a lot easier to work with threads.

You should realize that the only (easy) way to accomplish this, is by having the user wait until all work is done and then serve the page. A more complicated but also more responsive approach would be to use Ajax (via jQuery for example) to ask the server periodically how far the work has progressed. This way you can also provide some progress indicator.

Upvotes: 3

Tamara Wijsman
Tamara Wijsman

Reputation: 12348

Because a ThreadPool is designed to do that:

It provides a pool of threads that can be used to execute tasks, post work items, process asynchronous I/O, wait on behalf of other threads, and process timers.

I guess it's better to store the results on your server in a database when they are done.

And then you could use a timer and AJAX to periodically request if the process is done, if so, get data.

Upvotes: 3

Related Questions