VC++フォームでスレッドといっても、余程大きなプロジェクトじゃないと、効果は無いのでは。と思ったりもします。
ただ前回デリゲートをやった事だし、スレッドもデリゲートにほぼ同じだし、動作確認だけでも何とかしたいとDOS窓(コマンドプロンプト)にcl入れてコンパイル。
試しに、VC++フォームでサブスレッドを呼び出すだけのサンプルを作ってみました。
<注意点>
・前回のサンプルに、スレッド部分を追加しただけです。
・メインスレッド、サブスレッド1、サブスレッド2とあるので、競合違反が起きても良さそうな気がするのですが、何故か今のところ例外は発生していません。
・リッチテキストへの書き込みで、競合自体は起きているようです。
【サブスレッド生成】
Thread ^newThread1 = gcnew Thread(gcnew ThreadStart(this, &suForm::subThread1));
上記のスレッド生成を、下記の様にすると、デリゲートと同様であると分かるような気が・・・。
ThreadStart ^delethr = gcnew ThreadStart(this, &suForm::subThread1);
Thread ^newThread1 = gcnew Thread(delethr);
ややこしいのは、2行目でスレッドの呼び出しをカプセル化(多分、だと思う)してるところでしょうか。
お試し環境
WindowsXP 32bit Edition
Visual C++ 2008
/*---- VC++ Form 作成 ----------------- コマンドライン --------------------*/
D:\vc2008\dllchk>cl /clr testpp.cpp /link /subsystem:windows /entry:mainCRTStartup
/*----------------------------------------------------------------------------*/
/*---- testpp.cpp -------------------- お試しソース ------------------------*/
#using <system.dll>
#using <system.drawing.dll>
#using <system.windows.forms.dll>
using namespace System::Windows::Forms;
using namespace System::Threading;
ref class suText : public System::Windows::Forms::RichTextBox {};
ref class suButton : public System::Windows::Forms::Button {};
ref class suForm : public System::Windows::Forms::Form {
public :
suForm() {
initCompo();
}
~suForm() {}
private :
suText ^text1;
suButton ^button1;
suButton ^button2;
System::Windows::Forms::Label ^label1;
System::Drawing::Point pt;
System::String ^str;
void initCompo()
{
text1 = gcnew suText;
text1->Location = System::Drawing::Point(50, 50);
text1->Size = System::Drawing::Size(100, 150);
text1->BackColor = System::Drawing::Color::FromArgb(255, 255, 180);
text1->Name = "text1";
text1->Text = "求む入力!";
text1->MouseDown += gcnew System::Windows::Forms::MouseEventHandler(this, &suForm::text1_MouseDown);
button1 = gcnew suButton;
button1->Location = System::Drawing::Point(75, 220);
button1->Size = System::Drawing::Size(70, 20);
button1->BackColor = System::Drawing::Color::FromArgb(180, 255, 255);
button1->Name = "button1";
button1->Text = "未確認";
button1->Click += gcnew System::EventHandler(this, &suForm::button1_Click);
button2 = gcnew suButton;
button2->Location = System::Drawing::Point(160, 220);
button2->Size = System::Drawing::Size(70, 20);
button2->BackColor = System::Drawing::Color::FromArgb(180, 255, 255);
button2->Name = "button2";
button2->Text = "スレッド";
button2->Click += gcnew System::EventHandler(this, &suForm::button2_Click);
label1 = gcnew Label;
label1->Location = System::Drawing::Point(200, 120);
label1->Size = System::Drawing::Size(150, 20);
label1->Name = "label1";
label1->Text = "コンパイルエラーが来たぁ";
this->Location = System::Drawing::Point(50, 50);
this->ClientSize = System::Drawing::Size(400, 300);
this->StartPosition = FormStartPosition::Manual;
this->Name = "form1";
this->Text = "サンプルプログラム";
this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &suForm::form1_Paint);
this->Controls->Add(text1);
this->Controls->Add(button1);
this->Controls->Add(button2);
this->Controls->Add(label1);
}
System::Void text1_MouseDown(System::Object ^sender, System::Windows::Forms::MouseEventArgs ^event) {
pt = System::Drawing::Point(event->X, event->Y);
str = "X = " + event->X + ", Y = " + event->Y + ", Button = " + event->Button.ToString();
Invalidate();
}
System::Void button1_Click(System::Object ^sender, System::EventArgs ^event) {
label1->Text = "ボタンが押されました。";
label1->ForeColor = System::Drawing::Color::Red;
button1->Text = "押下";
button1->Enabled = false;
}
System::Void form1_Paint(System::Object ^sender, System::Windows::Forms::PaintEventArgs ^e) {
System::Drawing::Graphics ^g = e->Graphics;
System::Drawing::Brush ^brush = gcnew System::Drawing::SolidBrush(System::Drawing::Color::Blue);
g->DrawString(str, Font, brush, 200, 160);
g->FillRectangle(brush, pt.X + 150, pt.Y, 10, 10);
label1->Text = "コンパイルエラーが来たぁ";
label1->ForeColor = System::Drawing::Color(ForeColor);
button1->Text = "未確認";
button1->Enabled = true;
}
System::Void button2_Click(System::Object ^sender, System::EventArgs ^event) {
button2->Text = "開始";
button2->Enabled = false;
Thread ^newThread1 = gcnew Thread(gcnew ThreadStart(this, &suForm::subThread1));
newThread1->IsBackground = true;
Thread ^newThread2 = gcnew Thread(gcnew ThreadStart(this, &suForm::subThread2));
newThread2->IsBackground = true;
newThread1->Start();
newThread2->Start();
}
System::Void subThread1() {
for(int i = 0; i < 5; i++) {
text1->Text += ", i = " + i.ToString();
Thread::Sleep(1000);
}
button2->Text = "スレッド";
label1->Text = "例外発生1?";
}
System::Void subThread2() {
for(int j = 5; j < 15; j++) {
text1->Text += ", j = " + j.ToString();
Thread::Sleep(500);
}
button2->Enabled = true;
label1->Text = "例外発生2?";
}
};
void main()
{
Application::Run(gcnew suForm);
}
/*----------------------------------------------------------------------------*/
/*============================================================================*/