今回は、スレッドから Form上にあるボタンの許可禁止のアクセス方法についてまとめます。
VisualStadio2008 VC++ では
スレッドから直接 Form上のControlを制御するこは許されていません。
delegate と Invoke をしようすることで、スレッドから Form側のスレッドに処理を写し
Contorlを制御できるようにします。
以下の例は、
Form起動時にスレッドを起動、約2秒おきに button1(スレッド終了要求ボタン)を許可、禁止を
繰り返すものです。この許可禁止で、delegate と Invokeを使用しています。
namespace ThreadSample2 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Threading; // <------ 追加
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
}
:<略>
// Thread処理用メンバ宣言
Thread^ WorkThread;
ThreadStart^ WorkThreadDelegate;
bool thread_stop_req;
// Controlの制御のための delegate
delegate void fm1_void_void(void);
// button1許可
void button1_enb(void)
{
if(this->InvokeRequired){
// スレッドのときはここへ来る
fm1_void_void ^dgt = gcnew fm1_void_void(this,
&ThreadSample2::Form1::button1_enb); //Deleateオブジェクト
this->Invoke( dgt );
}
else {
// Invokeで呼び出すことで Formのプロセスでこちらへ来る
button1->Enabled = true;
}
}
// button1禁止
void button1_dsb(void)
{
if(this->InvokeRequired){
// スレッドのときはここへ来る
fm1_void_void ^dgt = gcnew fm1_void_void(this,
&ThreadSample2::Form1::button1_dsb); //Deleateオブジェクト
this->Invoke( dgt );
}
else {
// Invokeで呼び出すことで Formのプロセスでこちらへ来る
button1->Enabled = false;
}
}
// Thread処理メソッド
void ThreadProcessing(void)
{
bool enb_f;
enb_f = true;
button1_dsb();
while(true) {
Thread::Sleep(2000); // 約2秒Sleep
if(thread_stop_req==true)
break; // Thread停止要求があった
if(enb_f==true) {
button1_enb(); // button1許可
enb_f = false;
}
else {
button1_dsb(); // button1禁止
enb_f = true;
}
}
MessageBox::Show("Thread終了します。");
}
// Form1 起動時処理
private: System::Void Form1_Load(System::Object^ sender,
System::EventArgs^ e)
{
WorkThread = nullptr;
if(WorkThread==nullptr) {
// Thread生成
WorkThreadDelegate = gcnew ThreadStart(this,
&ThreadSample2::Form1::ThreadProcessing);
WorkThread = gcnew Thread(WorkThreadDelegate);
WorkThread->Start();
}
}
// スレッド停止要求
private: System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
thread_stop_req = true; // Thread終了要求
}
// Form終了時 処理
private: System::Void Form1_FormClosing(System::Object^ sender,
System::Windows::Forms::FormClosingEventArgs^ e)
{
bool bret;
thread_stop_req = true; // Thread終了要求
// Thread終了待ち
if(WorkThread!=nullptr) {
bret = WorkThread->Join(10000); // 10秒 Threadの終了を待つ
if(bret==true)
MessageBox::Show("正常終了。");
else
MessageBox::Show("Timeout終了。");
}
}
};
}
(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)