Re[6]: Как выполнить метод в другом (основном) потоке?
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 13.07.09 13:57
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>на данный момент (так как выяснилось, что 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() — прибиваем процесс разными способами.

З.Ы. Способ с самоостановкой все же какой-то кривой. Я не разу не видел службы которая бы принудительно себя бы прибивала. Возникла необрабатываемая ошибки — не обрабатывай ее и процесс будет прибит с записью в журнал событий и всеми вытекающими.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.