Выполнение задач параллельно в ASP.NET метод действия MVC 3
у меня есть действие поиска в ASP.NET MVC 3 приложение, которое возвращает предложения содержащих и предложения тегом с заданными ключевыми словами:
[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);
}
Я думаю containing
и tagged
запросы могут выполняться параллельно.
каков наилучший способ запустить эти два запроса одновременно, дождаться результатов и вернуться только после завершения обоих запросов?
3 ответов
библиотека задач Parallels-ваш лучший вариант. Много информации через Google, но ниже то, что ваша реализация может выглядеть.
[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);
}
имейте в виду, что если ваше приложение получает много запросов, вы можете быть лучше не выполнение ваших запросов асинхронно-потребляет 2 дополнительных потока для обслуживания одного запроса отнимает ресурсы от других входящих запросов. Это будет только проблема, если у вас огромный объем трафика, или если ваш аппаратное обеспечение неадекватно.
вы хотите быть осторожным, используя TPL из веб-страницы, поскольку TPL будет использовать потоки, которые в противном случае будут использоваться для обслуживания других HTTP-запросов. По сути, вы можете обменять более низкую задержку ответа на отдельные запросы на уменьшенную общую пропускную способность запросов.
см. Следующий пост для более подробного объяснения о компромиссах:
http://blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx
это может быть хорошим кандидатом на асинхронный контроллер. Важная вещь о асинхронных контроллерах заключается в том, что если вы хотите получить чистый прирост производительности в этом случае, вам нужно изменить уровень репозитория и предоставить асинхронные версии двух методов, которые в идеале используют порты завершения ввода-вывода при общении с удаленными системами, такими как база данных.
public class SearchController: AsyncController
{
public void SearchAsync(string query, int pg = 0)
{
// TODO: Write a custom model binder to do this job
// and have your controller action directly take an
// IEnumerable<string> argument.
var keywords = query.Split(new[] { ' ', ',', ';' },
StringSplitOptions.RemoveEmptyEntries);
AsyncManager.OutstandingOperations.Increment();
AsyncManager.OutstandingOperations.Increment();
_readonlySession.GetContainingCompleted += (sender, e) =>
{
AsyncManager.Parameters["containing"] = e.Value;
AsyncManager.OutstandingOperations.Decrement();
};
_readonlySession.GetTaggedCompleted += (sender, e) =>
{
AsyncManager.Parameters["tagged"] = e.Value;
AsyncManager.OutstandingOperations.Decrement();
};
_readonlySession.GetContainingAsync(keywords);
_readonlySession.GetTaggedAsync(keywords);
AsyncManager.Parameters["query"] = query;
}
public ActionResult SearchCompleted(string query, IEnumerable<Suggestion> containing, IEnumerable<Tag> tagged)
{
var model = new SearchViewModel
{
Query = query,
Containing = containing.ToList(),
Tagged = tagged.ToList()
};
return View(model);
}
}