[C ++, форма Windows] Как заставить основной поток ждать завершения вызываемого потока? - PullRequest
0 голосов
/ 14 ноября 2018

Я создал 2 кнопки, одну для начала новой темы, другую для ее завершения. Фактические вычисления внутри нового потока включали new [] и delete [], поэтому я не прерывал поток напрямую, а использовал флаг для его завершения. Для завершения удаления [] и сохранения результатов может потребоваться некоторое время, поэтому я хочу, чтобы основной поток дождался завершения нового потока. Но как бы я ни пытался, я обнаружил, что новый поток не запускается (хотя его ThreadState работает) до тех пор, пока не будут выполнены командные строки для кнопки остановки. System :: Threading :: Thread работает совсем не так, как поток для меня. Это так и должно быть?

#include "stdafx.h"

ref class Form1 : System::Windows::Forms::Form
{
public:
//define a thread name and a flag to terminate the thread
System::Threading::Thread^ th1;
static bool ITP1=0;

Form1(void)
{InitializeComponent();}

System::Windows::Forms::Button^ ButtonStart;
System::Windows::Forms::Button^ ButtonStop;
System::Windows::Forms::Label^ Label1;

void InitializeComponent(void)
{
    this->SuspendLayout();

    this->ButtonStart = gcnew System::Windows::Forms::Button();
    this->ButtonStart->Location = System::Drawing::Point(20, 20);
    this->ButtonStart->Click += gcnew System::EventHandler(this, &Form1::ButtonStart_Click);
    this->Controls->Add(this->ButtonStart);

    this->ButtonStop = gcnew System::Windows::Forms::Button();
    this->ButtonStop->Location = System::Drawing::Point(120, 20);
    this->ButtonStop->Click += gcnew System::EventHandler(this, &Form1::ButtonStop_Click);
    this->Controls->Add(this->ButtonStop);

    this->Label1 = gcnew System::Windows::Forms::Label();
    this->Label1->Location = System::Drawing::Point(20, 80);
    this->Controls->Add(this->Label1);

    this->ResumeLayout(false);
    }

void ThreadStart()
{
    for (int idx=0;idx<999999999;++idx)
    {
        if (ITP1) break;
    }
    this->Label1->Text = "finished";
    ITP1=0;
}

System::Void ButtonStart_Click(System::Object^ sender, System::EventArgs^ e)
{
    th1 = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this,&Form1::ThreadStart));
    th1->Start();
    this->Label1->Text = "running";
}

System::Void ButtonStop_Click(System::Object^ sender, System::EventArgs^ e)
{
    if (th1->ThreadState==System::Threading::ThreadState::Running)
    {
        //use the flag to stop the thread
        ITP1=1;
        //the wait method using while+sleep doesn't work
        while (th1->ThreadState==System::Threading::ThreadState::Running)   System::Threading::Thread::Sleep(1000);
        //replacing the wait method above with "th1->Join()" doesn't work either
    }
}
};

int main()
{
Form1^ A1 = gcnew Form1();
A1->ShowDialog();
return 0;
}

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Наконец я нашел причину.Это просто указатель "this->" в новом потоке.Удаление это делает все в порядке.Я полагаю, это потому, что форма позволяет работать только с одним элементом одновременно.Я прошу нажатие кнопки, чтобы дождаться нового потока, и новый поток пытается изменить другой элемент формы.Они ждут окончания друг друга и вызывают мертвую петлю.

0 голосов
/ 14 ноября 2018

Вы должны join() вызываемый поток в основном потоке.Тогда основной поток будет ждать, пока вызванный поток не закончится.

См. Документацию для Join, чтобы узнать, как это называется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...