#c# #multithreading #wcf #backgroundworker #scheduled-tasks
#c# #многопоточность #wcf #фоновый рабочий #запланированные задачи
Вопрос:
Я хочу разработать приложение доставки (автономный сервис WCF), которое позволяет планировать отправку электронных писем. Пользователь назначит расписание электронной почте и отправит его. Служба WCF должна иметь возможность выбирать электронное письмо и отправлять его в назначенное время.
Какой подход мне использовать здесь? Я думаю о следующих альтернативах
- Используйте фоновый рабочий поток для выполнения этой задачи
- Любая сторонняя служба планирования (мне еще предстоит разобраться в этом)
Кто-нибудь может предложить мне возможное решение для этого, кроме двух вышеупомянутых?
[Редактировать] : Могу ли я использовать агенты SQL для этого?
Спасибо,
ОЗУ
Комментарии:
1. хммм, означает ли это, что я буду получать больше электронных писем с расширением? 😉
Ответ №1:
Поставьте свою службу WCF в очередь запросов электронной почты либо в таблицу базы данных. Затем напишите службу Windows, которая периодически сканирует таблицу, отправляет электронное письмо, а затем обновляет таблицу результатами.
Если вы используете SQL Server, вы можете отправлять электронные письма непосредственно с него, а также планировать задания для отправки электронных писем, избавляя вас от необходимости развертывать службу Windows.
Комментарии:
1. Ой. Не подавайте в суд на базу данных в качестве очереди; используйте очередь. 🙂 MSMQ будет работать просто отлично, и при необходимости вы можете сохранить его на диске.
2. @Esteban Araya — почему бы и нет? В этом случае лучше использовать DB в качестве очереди, поскольку вы можете гарантировать ссылочную целостность, воспользоваться SQL и индексами.
3. @Alex Aza: Зачем очереди нужна ссылочная целостность? Зачем нужны показатели? Очередь есть очередь … и ничего больше.
4. @Esteban Araya — с практической точки зрения, это не просто очередь. У вас есть список элементов для обработки, но каждый из них должен обрабатываться по разному расписанию. После обработки элемента вы можете захотеть сохранить историю. В истории может потребоваться ссылка на расписания, электронные письма, пользователей и т.д.
Ответ №2:
Я видел «… кроме вышеупомянутых двух …», но я думаю, что нет ничего другого для достижения этого 🙂 Либо создайте бесконечный цикл внутри службы Windows следующим образом:
private void DoTheThing()
{
try
{
while (true)
{
TheThing e = new TheThing();
Thread t = new Thread(new ThreadStart(e.Run));
t.Start();
Thread.Sleep(1000);
}
}
catch (ThreadAbortException) { }
catch (Exception ex) { /* Whatever error handling you got */ }
}
… где у theThing есть метод Run, который выполняет все, что вам нужно, каждые 1 секунду. Это выглядит глупо (в то время как (true) — да, верно), но работает без остановок с .NET 1.0 как минимум на 30 серверах 🙂 Просто убедитесь, что вы вызываете этот метод doTheThing при запуске вашей службы Windows в новом потоке.
Надеюсь, это поможет 🙂
Комментарии:
1. Предлагаемое вами решение хорошее, однако я ищу альтернативу, потому что фоновый поток будет выполняться в течение всего срока службы службы WCF. Меня беспокоит то, что это не должно увеличивать сложность службы WCF или bottlenexk для других процессов.
2. В принципе, цикл хорош, каждая служба представляет собой цикл под капотом. Два момента, зачем создавать новый поток каждую секунду, что, если
TheThing()
он замедляется? Во-вторых, и это очевидно, не полагайтесь на задержку, равную ровно одной секунде, проверьте часы, чтобы узнать, который час, не считайте итерации.3. @Jodrell: 1. Поток. Sleep (1000) был просто примером для случаев, когда время не так важно. 2. В моих типичных проектах, где требуется фоновый цикл, задачи не зависят друг от друга, открытие каждой из них в новом потоке было бы предпочтительнее для меня именно по той причине, которую вы упомянули — если одна задача еще не завершена, а другая уже должна быть выполнена. Итак, вы абсолютно правы — запустите их в одном потоке, если они зависят друг от друга, или используйте решение, которое сохраняло бы и проверяло текущее состояние вещей.
4. @Ram: Судя по вашему сообщению и комментарию, вы рассматриваете веб-приложение в качестве хоста для своей службы WCF. Я не думаю, что веб будет работать для вас, потому что IIS перерабатывает простаивающие веб-приложения. Вы должны разместить свой WCF в службе Windows. Отредактируйте мой пример кода и комментарии.
5. Вы правы, не используйте службу, размещенную в IIS, для планирования событий, пулы приложений сбрасываются непредсказуемо, было бы лучше перейти на
at
(не самый лучший или даже хороший). Я просто пытался предупредить случайного читателя о потоке. Sleep (), я вижу, вы не злоупотребляли им. Наконец, еслиTheThing
был статичным, но медленным, вы могли бы в конечном итоге столкнуться со многими потоками, использующими память, конкурирующими за ресурсы и, в конечном итоге, замораживающими службу или даже систему, несмотря на то, что код является независимым от id.
Ответ №3:
Это зависит от ваших нефункциональных требований… 🙂
Я могу представить, что вы хотели бы некоторой надежности в этом сервисе. Время жизни службы WCF зависит от ее хоста. Например. если это IIS, пул приложений будет переработан после определенного времени простоя (запросы в IIS не поступают). Это потребовало бы другого решения, чем фоновый рабочий. Как вы предполагаете, это может быть сторонний планировщик, но в Windows также есть планировщик. (см.http://technet.microsoft.com/en-us/library/dd363786 (WS.10).aspx) С помощью небольшой консольной программы вы могли бы попросить планировщик Windows вызвать вашу службу или, в качестве альтернативы, отправить само электронное письмо.
Комментарии:
1. Служба WCF не обязательно должна размещаться в IIS. В этом случае это должна быть служба Windows.
2. верно, но эта информация отсутствует в вопросе. В этом случае фоновый рабочий мог бы выполнить работу отлично, с точки зрения надежности. Тем не менее, вы все равно могли бы использовать внешний механизм планирования…
3. Я думал, что это было очевидно, что это не IIS. Даже если это был IIS, обрабатывающей частью должна быть служба Windows или даже запланированное консольное приложение.
4. Я полагаю, что мы согласны с тем, что вопрос не является исчерпывающим в требованиях и контексте. Все, что я могу сделать, это привести несколько примеров и указателей…