Как реализовать очереди фоновой обработки в веб-приложении ASP.NET MVC? Хотя большинство изменений данных, обновлений и т.д. должны быть видны немедленно, есть и другие обновления, которые не требуют обработки в реальном времени, которые я хотел бы передать фоновому процессу с более низким приоритетом, который будет заниматься ими в своем собственном темпе.
В качестве примера можно привести систему награждения бейджами StackOverflow'. Обычно вы можете совершить определенное действие, которое наградит вас бейджем, но само награждение происходит позже (обычно от 10 минут до пары часов). Я предполагаю, что это делается через отдельный фоновый процесс, так как для работы SO' не критично, чтобы бейджи присуждались сразу после их получения.
Итак, я пытаюсь создать некую систему очередей, в которую я мог бы запихивать задачи (скажем, что-либо, реализующее интерфейс ITask, у которого будет метод Process()), которые в конечном итоге будут выполняться отдельным процессом.
Как мне реализовать такую систему? Идеи/подсказки/пример кода?
Спасибо!
Службы Windows и MSMQ для взаимодействия с ними (если это вообще нужно).
-- Редактировать
Чтобы немного расширить.
Вы создаете несколько служб, в зависимости от того, что вы хотите сделать, и заставляете их всех запускать бесконечный поток различных уровней сна, чтобы сделать то, что вы хотите. Затем они соответствующим образом обновят базу данных, и вам не придется ничего делать на стороне клиента.
Вы можете захотеть взаимодействовать с ними с точки зрения администратора, поэтому у вас может быть MSMQ, на котором они прослушивают команды администратора. В зависимости от вашей реализации, вам может понадобиться перезапустить их по какой-то причине, или, возможно, просто 'заставить' запустить то, что они хотят сделать.
Поэтому для этого вы будете использовать MSMQ Private Queue (пространство имен System.Messaging). Одна из главных особенностей MSMQ заключается в том, что сообщения должны быть размером <4 мегабайта. Поэтому, если вы собираетесь отправлять большие графы объектов, сначала сериализуйте их в файл и просто отправьте имя файла.
MSMQ довольно красив. Вы можете отправлять на основе 'ID корреляции', если вам это нужно, но, по какой-то забавной причине, ID корреляции должен быть в форме:
{guid}\1
Все остальное не работает (по крайней мере, в версии 2.0 фреймворка, код мог измениться).
-- Редактировать
Пример, как просили:
using System.Messaging;
...
MessageQueue queue = new MessageQueue(".\\Private$\\yourqueue");
queue.Formatter = new BinaryMessageFormatter();
Message m = new Message();
m.Body = "your serialisable object or just plain string";
queue.Send(m);
// on the other side
MessageQueue queue = new MessageQueue(".\\Private$\\yourqueue");
queue.Formatter = new BinaryMessageFormatter();
Message m = queue.Receive();
string s = m.Body as string;
// s contains that string now
У Джеффа есть отличный пост, показывающий, как он добился этого первоначально для Stack Overflow по адресу http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/.
Хотя он может быть не таким надежным, как сервис, если это для вас вариант, он хорошо послужил мне в прошлом для не основных задач, и я работал с ним в среде виртуального хостинга.
Только что нашел этот вопрос при поиске фонового процесса в ASP.NET MVC. (Доступно после .NET 4.5.2)
public ActionResult InitiateLongRunningProcess(Emails emails)
{
if (ModelState.IsValid)
{
HostingEnvironment.QueueBackgroundWorkItem(ct => LongRunningProcessAsync(emails.Email));
return RedirectToAction("Index", "Home");
}
return View(user);
}
Примечание: Лично я'не буду использовать веб-сервер для запуска фоновых задач. Также не стоит изобретать велосипед, я бы настоятельно рекомендовал использовать Hangfire.
Прочитайте эту замечательную статью от Hanselman HowToRunBackgroundTasksInASPNET.