Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running tasks in parallel in ASP.NET MVC 3 Action method

I have a Search action in an ASP.NET MVC 3 app that returns suggestions containing and suggestions tagged with the given keywords:

[HttpPost]
public ActionResult Search(string query, int pg = 0)
{
    var keywords = query.Split(new[] { ' ', ',', ';' }, 
        StringSplitOptions.RemoveEmptyEntries);

    var containing = (from s in _readonlySession.All<Suggestion>()
                      from k in keywords
                      where (s.Text.ToLower().Contains(k.ToLower()))
                      orderby s.Text
                      select s).Distinct();

    var tagged = (from t in _readonlySession.All<Tag>()
                  from s in t.Suggestions
                  from k in keywords
                  where t.Text.ToLower().Contains(k.ToLower())
                  orderby s.Text
                  select s).Distinct();

    var model = new SearchViewModel
    {
        Query = query,
        Containing = containing.ToList(),
        Tagged = tagged.ToList()
    };

    return View(model);
}

I think the containing and tagged queries could be perfectly run in parallel.

What is the best way to fire these two queries at the same time, wait for the results, and return only when both queries are completed?

like image 850
Sergi Papaseit Avatar asked Apr 06 '11 23:04

Sergi Papaseit


1 Answers

The Task Parallels Library is your best option. Plenty of information via Google, but below is what your implementation might look like.

[HttpPost]
public ActionResult Search(string query, int pg = 0)
{
    var keywords = query.Split(new[] { ' ', ',', ';' }, 
        StringSplitOptions.RemoveEmptyEntries);

    IEnumerable containing=null;
    Task t1 = Task.Factory.StartNew(() =>
    {
        containing = (from s in _readonlySession.All<Suggestion>()
                        from k in keywords
                        where (s.Text.ToLower().Contains(k.ToLower()))
                        orderby s.Text
                        select s).Distinct().ToList();

    });

    IEnumerable tagged=null;
    Task t2 = Task.Factory.StartNew(() =>
    {
        var tagged = (from t in _readonlySession.All<Tag>()
                        from s in t.Suggestions
                        from k in keywords
                        where t.Text.ToLower().Contains(k.ToLower())
                        orderby s.Text
                        select s).Distinct().ToList();
    });

    t1.Wait();
    t2.Wait();

    var model = new SearchViewModel
    {
        Query = query,
        Containing = containing.ToList(),
        Tagged = tagged.ToList()
    };

    return View(model);
}

Bear in mind that if your application gets a lot of requests, you may be better off not performing your queries asynchronously - consuming 2 extra threads to service one request takes resources away from other incoming requests. This will only be an issue if you have a huge volume of traffic, or if your hardware is inadequate.

like image 82
Greg Sansom Avatar answered Sep 22 '22 13:09

Greg Sansom