Завершение многопоточного приложения
От: Аноним  
Дата: 07.11.07 09:04
Оценка:
Приложение работает в несколько потоков. Если пользователь желает завершить приложение, закрывая основную форму, то остальные потоки нельзя рубить по Thread.Abort так как это приводит к ошибкам API и повреждению данных. Соответственно сделал в классах тех потоков свойство Stop, которое можно выставить в false и соответственно произойдет корректное завершение работы. Выглядит это примерно так:
class ShowOnMap{
  ...
  private bool stop = false;
  object thisLock = new object();
  public bool Stop {
    get{return stop;}
    set{lock(thisLock){stop = value;}}
  }
  ...
  public void Show()
  {
    ...
    while(... && !stop){
      ...
      lock(thisLock){
        ...
      }
      ...
    }
  }
}

Обработчик закрытия формы (а это означает, что пользователь хочет завершить приложение) выглядит примерно так:
if (thrShowOnMap != null){ // Проверка, что поток работающий с классом ShowOnMap существует
  showOnMap.Stop = true; // Сигнализация о необходимости завершить работу объекту класса ShowOnMap 
  thrShowOnMap.About(); // Попытка прерывание поток (должно произойти после корректного прекращения работы объекта класса ShowOnMap
  Thread.Sleep(1000); // Ожидание, для корректного завершения потока
}

Все это дело достаточно успешно работало, но поскольку потоков было несколько, то для каждого в закрытии формы был прописан соответствующий код завершения (там разные классы в разных потоках работают). И время закрытия формы было никак не меньше чем количество потоков помноженное на одну секунду (Thread.Sleep(1000). Рассудив, что это неправильно — пользователь жмет заркрыть форму, а она продолжает висеть на экране и ни на что не реагировать в течении нескольких секунд, я вынес процесс прекращения обработки данных и остановки потоков в отдельный поток, специально созданный для этой цели. Форма же закрывалась сразу. Таким образом, после закрытия формы, приложение на самом деле еще работает несколько секунд и при желании пользователь может его наблюдать в списке процессов. Меня это не смущает. Однако хочу знать, что остальные разработчики думают о таком подходе?
Re: Завершение многопоточного приложения
От: _FRED_ Черногория
Дата: 07.11.07 10:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Соответственно сделал в классах тех потоков свойство Stop, которое можно выставить в false и соответственно произойдет корректное завершение работы.


Почему не сделано "по-человечески" с использованием, например, ManualResetEvent?
Help will always be given at Hogwarts to those who ask for it.
Re: Завершение многопоточного приложения
От: akarinsky Россия  
Дата: 07.11.07 10:12
Оценка:
Здравствуйте, Аноним, Вы писали:

>>>...Однако хочу знать, что остальные разработчики думают о таком подходе?


Ага, знакомая история. Проблема может быть в том, что какой-то из потоков просто зависнет при закрытии (или уже висел) — тогда Ваша прога будет вечно ждать окончания работы, занимая ресурсы. Так что не стоит отказываться от Abort; один из вариантов — завести обертку над ThreadPool и сделать перегруженный вариант EnqueueWorkItem с параметром TimeStamp timeout.
Ну и при завершении все-таки лучше показать пользователю, что прога еще работает.
Впрочем, дело хозяйское
На опушке за околицей мужики строили коровник.
Работали споро и весело. Получалось х**во.
Re[2]: Завершение многопоточного приложения
От: Аноним  
Дата: 07.11.07 10:15
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


А>>Соответственно сделал в классах тех потоков свойство Stop, которое можно выставить в false и соответственно произойдет корректное завершение работы.


_FR>Почему не сделано "по-человечески" с использованием, например, ManualResetEvent?

Не умею. Никогда с потоками раньше не работал.
А что собственно ManualResetEvent изменит? Если я правильно понимаю, то всего лишь будет переданна информация о наступлении некоего события.
Re[3]: Завершение многопоточного приложения
От: _FRED_ Черногория
Дата: 07.11.07 10:22
Оценка:
Здравствуйте, Аноним, Вы писали:

_FR>>Почему не сделано "по-человечески" с использованием, например, ManualResetEvent?

А>Не умею. Никогда с потоками раньше не работал.

Вот тебе и повод изучить и опробовать. Начать советую с какой-нить книги Рихтера, Джефри.
Help will always be given at Hogwarts to those who ask for it.
Re: Завершение многопоточного приложения
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.12.07 03:36
Оценка: 2 (2)
Здравствуйте, <Аноним>, Вы писали:
А>Все это дело достаточно успешно работало, но поскольку потоков было несколько, то для каждого в закрытии формы был прописан соответствующий код завершения (там разные классы в разных потоках работают). И время закрытия формы было никак не меньше чем количество потоков помноженное на одну секунду (Thread.Sleep(1000).
Поэтому вместо пристрелки потоков по очереди, нужно делать так:
1. Оповещаем все потоки о том, что пора закрываться.
2. Ждем все потоки в течение некоторого таймаута (например, 10 секунд).
При помощи WaitForMultipleObjects.
3. Тех, кто не успел стопнуться добровольно, придется пристрелить.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.