Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>на данный момент (так как выяснилось, что SynchronizationContext не работает "нормально" с консольными приложениями такой костыль (?):
А>>А>>class MyService: ServiceBase
А>>{
А>> // ... здесь запускается поток в котром выполняется вся работа сервиса
А> void OnStop()
А> {
А> lock (sync)
А> {
А> if (!thread.IsAlive)
А> return;
А> thread.Abort();
А> thread.Join();
А> }
А> }
А>> // здесь тело метода выполняющего работу
А>> void ThreadWork()
А>> {
А>> try
А>> {
А>> }
А>> catch (Exception ex)
А>> {
А>> // log exception
А>> }
А>> context.Post(delegate {
А> thread.Join();
А> Stop();
А> }, null);
А>> }
А>>}
А>>
А>оцените плиз!
Ну, тут как минимум серьезный вопрос к архитектуре.
Во-первых, есть понятие активной сущности (см. Мейера), т.е. сущности, которая может сама в произвольный момент времени выполнять некоторые операции. Обычно то, что сущность является активной может быть скрыто от посторонних глаз.
Т.е. у тебя есть disposable класс MyService, который и выполняет всю работу. Не нужно для этого явно создавать поток в коде службы. Как минимум, таким способом ты облегчишь написание служб. У меня всегда есть бизнесс-сущности, которые я могу использовать как в консольном приложении (для простоты отладки) так и в сервисе. Процесс отладки запуска служб существует, но зачем идти так сложно? Закон один класс — одна задача, еще никто не отменял. А у тебя один класс (класс службы) занимается и проблемами потоков и проблемами служб и, видимо, кучей других проблем.
Во-вторых, когда твой класс MyService понял, что он не может больше выполнять свою работу, почему он не может попытаться восстановить свое состояние самостоятельно? Если же он сделать по какой-то причине он этого не может то тут тоже есть несколько способов решения этой проблемы. Если в сервисе произошла ошибка, после которой он не может восстановить свою работу, так и не обрабатывайте эту ошибку. Пусть ошибка будет необработана и CLR сама закроет ваш процесс, с записью в журнал события о необработанной ошибке. Если и этот вариант не подходит, то лучше у класса MyService сделать какое-то событие, типа ServiceFailed (или что-то в этом духе), которое говорит о том, что сервис таки сдох. И теперь уже на уровне службы прибивай этот процесс одним из следующих способов (наверняка есть еще куча других):
ServiceController.Stop() — посылаем SCM сообщение с желанием остановки службы
Environment.Exit(), Environment.FailFast(), Process.GetCurrentProcess().Close() — прибиваем процесс разными способами.
З.Ы. Способ с самоостановкой все же какой-то кривой. Я не разу не видел службы которая бы принудительно себя бы прибивала. Возникла необрабатываемая ошибки — не обрабатывай ее и процесс будет прибит с записью в журнал событий и всеми вытекающими.