2010-02-15 3 views
4

У меня есть класс, который внутренне использует рабочий поток. В настоящее время ctor запускает поток, и dtor останавливается (и ждет) его. Это считается хорошим кодом? Я думаю, было бы лучше иметь отдельные функции start()/stop() для этой цели.start/stop thread in ctor/dtor или лучше использовать start()/stop()?

Одна из проблем заключается в том, что остановка и ожидание потока могут вызывать исключения, что плохо в dtor.

Что бы вы мне совет:

  1. оставить код, как это и просто поймать и журнал исключений в dtor
  2. использование start()/stop(), пусть исключения клиента ручки и просто удалите нить в dtor (и выдать предупреждение о нечистом отключении или что-то еще)

ответ

4

Я бы, вероятно, не начал нить в конструкторе, а имел функцию запуска. Если рабочий поток в основном невидим для пользователя, то это может иметь мало значения, и начало в конструкторе может быть лучше. Но если пользователь каким-либо образом взаимодействует с рабочим потоком (например, их код запускается в нем), то в конечном итоге кому-то нужно будет создать определенное состояние после создания объекта, но до запуска потока. Закон Мерфи гарантирует это ;-)

Я бы остановил его в деструкторе и поймал и зарегистрировал исключение. Если пользователю, вероятно, потребуется знать результат остановки (например, если сбой означает, что рабочий поток, возможно, не выполнил свою работу), то также есть функция остановки, которую они могут запросить, чтобы получить эту информацию.

К тому же, есть некоторые технические проблемы, связанные с началом потока в конструкторе вообще. Новый поток будет потенциально запускаться до того, как конструктор вернется в старый поток. Если он обращается к своему объекту владельца (например, для отчета о результатах), он может поэтому получить доступ к не полностью сконструированному объекту. Это обычно легко обойти, вплоть до того момента, когда вы наследуете свой первоначальный класс. Теперь поток запускается до запуска конструктора производного класса, что может вызвать всевозможные проблемы. Поэтому, если вы начинаете поток в конструкторе, и поток может получить доступ к объекту прямо или косвенно, позаботьтесь и оставите много предупреждений.

+0

Я уверен, что при запуске конструктора гарантированно будет полностью построенный объект. Единственная проблема, с которой вы могли бы позвонить в чистые виртуальные функции. –

+0

@aiwarrior: Если конструктор базового класса запускает поток, а конструктор производного класса выполняет некоторое действие X, тогда код, запущенный в новом потоке, может видеть объект до того, как произойдет действие X. Поэтому объект не полностью построен. –

+0

Я согласен, что стоит упомянуть. Читая более внимательно, вы подразумеваете, что это просто потенциал. Я был nitpicking, потому что это опасно только тогда, когда наследование является ожидаемым, и, конечно, если язык позволяет ... то он ожидаемый. Хорошее объяснение. –

0

Зависит от семантики класса. Если ему нужна внутренняя резьба, хорошо начать/остановить поток без вмешательства извне.

Хорошим может быть использование пула потоков, то есть повторное использование потоков, отбрасываемых предыдущим экземпляром класса.

1

Я не вижу оба варианта как взаимоисключающие. Вот как я это сделаю:

{ 
    mythread worker1; // starts 
    mythread worker2(false); // doesn't start 
    worker2.start(); 

    worker1.stop(); 

} // dtor. of worker2 stops it, dtor. of worker1 does nothing 
Смежные вопросы