Удаление wxWidgets wxThread для объединяемого потока

#c #multithreading #wxwidgets

#c #многопоточность #wxwidgets

Вопрос:

У меня возник вопрос о объединяемых потоках в wxWidgets.

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

Есть ли у меня возможность остановить поток (используя TestDestroy) или мне нужно полностью изменить свой код?

Заранее спасибо,

ТиБо

Ответ №1:

Текущая документация для wxThread::Delete() гласит:

Эта функция работает с объединяемым потоком, но в этом случае функция TestDestroy() потока возвращает значение true, а затем ожидает его завершения (т. Е. Она отличается от Wait() тем, что запрашивает завершение потока перед ожиданием).

Итак, похоже, что вы можете использовать Delete() в объединяемом потоке.

Комментарии:

1. О да.. Только в последних стабильных документах говорится, что вы не должны делать это для объединяемого : (

2. В документации говорится, что не следует использовать оператор удаления ie. delete m_thread но вы всегда можете использовать m_thread->delete()

Ответ №2:

Вы должны вызвать метод Exit() из вашего рабочего потока или просто вернуться из метода Run и вызвать метод MyThread-> Wait(), а затем удалить объект thread.

Объявление потока :

 class MyThread : public wxThread {
  virtual void * run();
};
  

Реализация потока :

 MyThread::run()
{
  while(1)
  {
    if(TestDestroy())
    {
        this.Exit();  // or return;
    }
    // Do some work
  }
}
  

Объявление указателя потока :

 MyThread * pMyThread;
  

Создание, запуск и остановка потока

 void launchThread{
  pMyThread = new wxThread(wxTHREAD_JOINABLE);
  pMyThread->Create();
  pMyThread->Run();
}

void stopThread(){
  pMyThread->Delete();
  pMyThread->Wait();
  delete pMyThread;
}
  

Надеюсь, что это поможет.

PS: это мой первый ответ на переполнение стека. Я не знаю, как я могу легко написать какой-нибудь код с автоматическим отступом?

Комментарии:

1. Я полагаю, что вызов Delete() объединяемого потока заставляет его ждать завершения потока, поэтому вам не нужно Wait() после Delete() ввода stopThread() . Wait() Может просто корректно возвращаться, но это избыточно, хотя я не тестировал ваш код.

2. Нет, он укажет потоку на удаление. Единственное, что TestDestroy() вернет true, тогда поток должен завершиться(). Позже вам придется вызвать Wait() из вызывающего потока (чтобы освободить «используемые им системные ресурсы»), после чего вы сможете удалить объект, на котором выполняется поток.

Ответ №3:

Вам не придется переписывать свой код.

Обычно лучше, чтобы поток завершался возвратом из его основной функции, как предлагает документация.

Один из способов достижения этого, и, вероятно, самый простой, — создать некоторый объект, который будет перехвачен функцией основного потока.

Например:

 struct ThreadEndingException { };

void DoSomeWork() {
    ...
    if (TestDestroy())
        throw ThreadEndingException();
    ...
}

void ThreadFunction() {
    try {
        DoSomeWork();
    }
    catch (const ThreadEndingExceptionamp;) {
        // Do nothing, the function will return after leaving this catch.
    }
}
  

Комментарии:

1. Спасибо за ответ; Но проблема, с которой я столкнулся, заключается в том, что я не знаю, как установить «TestDestroy()-flag». Это кажется возможным только с помощью Delete() , но это не должно использоваться объединяемыми потоками, как говорится в документальном фильме…