VC++フォームでのスレッドも、コマンドプロンプトでEXE?

|

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);
}

/*----------------------------------------------------------------------------*/
/*============================================================================*/