2016-03-03 2 views
3

std::thread::join не возвращается, даже если процедура потока завершена.std :: thread :: объединение блоков на неопределенное время из основного

Угадайте, у меня есть класс.

class A 
{ 
public: 
    A() 
    { 
     this->thr = std::thread(&A::foo, this); 
    } 
    ~A() 
    { 
     this->join(); 
    } 
    void join() 
    { 
     this->cond.notify_all(); 
     if (this->thr.joinable()) 
     { 
      this->thr.join(); 
     } 
    } 

private: 
    void foo() 
    { 
     std::mutex mtx; 
     std::unique_lock<std::mutex> lck(mtx); 
     this->cond.wait(lck); 
     MessageBox(L"I'm done!"); 
    } 

private: 
    std::thread thr; 
    std::condition_variable cond; 
}; 

Мое приложение содержит единственный экземпляр A. Это глобальная переменная. Если A::join вызывается из деструктора, std::thread::join блоки навсегда. Если я вызываю A::join вручную (например, перед выходом main), все в порядке.

Мои main выглядит следующим образом:

A a; 
int main() 
{ 
    auto timeout = std::chrono::seconds(3); 
    std::this_thread::sleep_for(timeout); 

    // a.join(); 
} 

Кстати, MessageBox всегда выполняется.

Это та же проблема, что и here?

+0

Был ли [ответ] (http://stackoverflow.com/a/17239943/2069064) не ответил на ваш вопрос? – Barry

+0

@Barry, Это не похоже на отличное решение. Я работаю, но что, если «главное» не так тривиально? Существует много разных способов выхода из моего приложения. Таким образом, мне нужно «присоединяться» к моим потокам вручную каждый раз, когда мне это нужно? –

+0

@MAKAKOKO Извините, я был смущен тем, что происходило. Я отозвал комментарий. – NathanOliver

ответ

3

Да, это та же ошибка, что и в ссылке, так как ваш пример также зависает на _Thrd_join. Вас так же могут заинтересовать: this question, который содержит гораздо более подробный анализ.

+0

Вот и все! К сожалению, я не могу проголосовать. Большое спасибо. –

+1

@JohnSmith как человек, который считает VS наилучшей возможной IDE такими ошибками во время выполнения, мне грустно :( –

1

от вашего комментария

«Это, кажется, не быть отличным решением. Я работает, но что, если основная не так тривиально? Там вы много различных способов выхода из мое приложение .Таким образом, мне нужно присоединяться к моим потокам вручную каждый раз, когда мне нужен ? "

Как насчет того, чтобы сделать A std :: unique_ptr в вашем главном. таким образом, независимо от того, как ваши основные выходы, он всегда будет уничтожать A перед выходом из main(), и у вас не будет этой проблемы.

Смежные вопросы