sample04

WinMain やめて main に移行
[STAThreadAttribute]
int main(array<System::String ^> ^args){}
で終了時のエラー消えた


// sample04.cpp
// add a button with click handler and also add a textbox
#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;

ref class MyForm : public Form
{
public:
    MyForm();
    Label ^m_label;
    Button ^btn;
    TextBox ^txt1;
    void btn_Click(Object ^sender, System::EventArgs^ e);
};

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    Application::Run(gcnew MyForm()); // message loop
    return 0;
}

MyForm ::MyForm()
{
    //set some form properties/fields
    this->Text = "sample04";
    this->FormBorderStyle=::FormBorderStyle::Fixed3D;
    this->MaximizeBox=false;
    this->ClientSize=System::Drawing::Size(400,300);

    //create the Label object and set its properties/fields
    m_label=gcnew Label();
    m_label->Text="The quick brown fox jumps over the lazy dog.";
    m_label->Size=System::Drawing::Size(300,50);
    m_label->Location=Point(5,5);

    //add the label to the form
    this->Controls->Add(m_label);

    btn=gcnew Button();
    btn->Text="Test Button";
    btn->Location=Point(5,90);
    btn->Size=System::Drawing::Size(100,22);
        btn->Click += gcnew EventHandler( this, &MyForm::btn_Click);

    //add the button
    this->Controls->Add(btn);

    txt1=gcnew TextBox();
    txt1->ReadOnly=true;
    txt1->Size=System::Drawing::Size(200,22);
    txt1->Location=Point(130,90);

    //add the text box
    this->Controls->Add(txt1);
}

//the event handler for button click
void MyForm::btn_Click(Object ^sender, System::EventArgs ^e)
{
    //we show the current date/time in the text box
    DateTime dt=System::DateTime::Now;
    txt1->Text=dt.ToString();
}

cat makefile
TARGET=sample04

all: $(TARGET).exe

.PHONY: all test mmm clean
.SUFFIXES: .obj
OBJS=$(TARGET).obj

$(TARGET).obj: $(TARGET).cpp

$(TARGET).exe: $(OBJS)
        link $(OBJS)

.cpp.obj:
        cl -c -Wall -Od -clr $<

test:
        ./$(TARGET).exe &

clean:
        -rm $(TARGET).exe *.obj *~

mmm:
        cat $(TARGET).cpp
        @echo
        cat makefile

html:
        cat /dev/clipboard | code2html.exe | unix2dos


COM スレッディング入門

プロセス
仮想メモリ空間、コード、データ、およびシステム リソースのコレクション
スレッド
プロセスの中でシリアルに実行されるコード
プロセッサが実行するのは、プロセスではなくスレッド
プロセス間通信
メッセージを使って互いに通信
プロセス間での情報の受け渡しには RPC 使用
COM
3 つのマルチスレッディング モデルを定義
昔の分類
シングル スレッド プロセス : 1 つのシングル スレッド アパートメントだけから構成されているプロセス
アパートメント モデル プロセス : 複数のシングル スレッド アパートメントを持ち、マルチスレッド アパートメントを持たないプロセス
フリー スレッド プロセス : 1 つのマルチスレッド アパートメントを持ち、シングル スレッド アパートメントを持たないプロセス
混合モデル プロセス : 1 つのマルチスレッド アパートメントと、1 つまたは複数のシングル スレッド アパートメントを持つプロセス
スレッディング モデルの考え方
すべてのプロセスがアパートメント モデル
アパートメントによって 1 つのスレッドを持つのか、複数のスレッドを持つのかの違いがあるだけ
スレッディング モデルは、実際にはプロセスではなくアパートメントに適用されるもの
オブジェクトのクラスにも適用できる
DLL などのコンポーネントにではなく、DLL の中のオブジェクト クラスに適用
1 つの DLL の中には、異なるスレッディング モデルを持つ複数のクラスが存在できる
スレッド実行
ルーチンが終了するまで実行
高い優先順位を持つスレッド、ユーザーのアクション、またはカーネルのスレッド スケジューラによって中断されるまで実行
コードのセクション
複数のスレッドが同じコードのセクションを実行可能
同じコードのブロックを実行しているスレッドは、それぞれ別のスタックを持つ
プロセスの中の各スレッドは、そのプロセスのグローバル変数とリソースを共有
MicrosoftR Windows NTR スケジューラ
プロセスの優先順位クラス属性とスレッドの基本優先順位の組み合わせに従って、スレッドの実行頻度を決定
プロセスの優先順位クラス属性を設定するには、MicrosoftR Win32R 関数のSetPriorityClass()を呼び出す
スレッドの基本優先順位を設定するにはSetThreadPriority()を呼び出す
スレッディング関連の問題
デッドロック
競合
デッドロック
すべてのスレッドが、他のスレッドが何かを実行するのを互いに待っているときに起こる
競合条件
あるスレッドが、それが依存している別のスレッドよりも前に終了したときに、後者がまだ値の準備を行っていないために、前者のスレッドが無意味な値を得てしまうという状況
OLE 呼び出しコントロール
異なるアパートメントに含まれているオブジェクト間の呼び出しでデッドロックが起こるのを防ぐ
OLE
プロセス外サーバーで競合条件が起こるのを防ぐことを目的に設計されている関数をいくつか用意
OLE のスレッディング アーキテクチャ
プロセスの中のすべての COM オブジェクトがアパートメントと呼ばれる複数のグループに分割されている
COM オブジェクト
1 つのアパートメントの中に存在
そのオブジェクトのメソッドは、そのアパートメントに属するスレッドからしか直接に呼び出せない
別のスレッドがこのオブジェクトを呼び出そうと思えば、プロキシを経由する必要がある
アパートメント
シングル スレッド アパートメント
マルチスレッド アパートメント
シングル スレッド アパートメント
OLE を使用するすべてのスレッドは、それぞれ独自のアパートメントの中に存在し、OLE は着信したすべての呼び出しをウィンドウ メッセージ キューを使って同期させる
1 つの実行スレッドを持つプロセスは、このモデルの特殊なケース
シングル スレッド アパートメントはちょうど 1 つのスレッドから構成され、シングル スレッド アパートメントの中に存在しているすべての COM オブジェクトは、そのアパートメントに属する 1 つのスレッドからのメソッド呼び出ししか受け取ることができない。
シングル スレッド アパートメントの中の COM オブジェクトに対するすべてのメソッド呼び出しは、そのシングル スレッド アパートメントのスレッドのウィンドウ メッセージ キューによって同期されru
マルチスレッド アパートメント
1 つのフリー スレッド アパートメントの中の複数のスレッドが OLE を使用し、OLE オブジェクトへの呼び出しはオブジェクト自身によって同期される
マルチスレッド アパートメントは 1 つまたは複数のスレッドから構成され、マルチスレッド アパートメントの中に存在しているすべての COM オブジェクトは、そのマルチスレッド アパートメントに属する任意のスレッドから、メソッド呼び出しを直接に受け取る
マルチスレッド アパートメントの中のスレッドはフリー スレッディングと呼ばれるモデルを使用
OLE は、MTA の中の COM オブジェクトに対するメソッド呼び出しに関しては同期処理をしない
COM オブジェクトは、必要ならば同期処理を独自に用意必要
クリティカル セクション、ミューテックス、またはセマフォを使ってコンポーネントの中のスレッドをシリアル化し、スレッドが終了状態を通知するのを待つ
シングル スレッド プロセス
プロセスの中では、最初にメイン アパートメントが初期化
唯一のアパートメント
呼び出しパラメータはアパートメント間でマーシャリング(整理)
OLE はメッセージングを通して同期処理を行う
プロセスの中の複数のスレッドをフリー スレッドとして指定
すべてのフリー スレッドが同じアパートメントの中に置く
アパートメント内では任意のスレッドにパラメータが直接に渡される
同期処理はすべてプログラマが自ら行う
フリー スレッディングとアパートメント スレッディングの両方が使われているプロセス
すべてのフリー スレッドが 1 つのアパートメントの中に入りる
個々のアパートメント スレッドはそれぞれ独自のアパートメントを持つ
OLE の操作を行うプロセスは、1 つのマルチスレッド アパートメントと、任意の数のシングル スレッド アパートメントから構成される、複数のアパートメントのコレクションとなる
異なるスレッディング アーキテクチャを使用するクライアントとサーバーが協調して動作
異なるプロセスの中の異なるスレッディング モデルを使用しているオブジェクト間での呼び出しOK
呼び出し元のオブジェクトから見ると、プロセスの外にあるオブジェクトへのすべての呼び出しは、呼び出される側のオブジェクトがスレッド化されているかどうかにかかわらず、まったく同じように振る舞う
呼び出される側のオブジェクトから見ると、到着した呼び出しは、呼び出し元のスレッディング モデルにかかわらず、まったく同じように振る舞う
クライアントとプロセス外オブジェクトの間の対話
両者が異なるスレッディング モデルを使っている場合で、クライアントとオブジェクトが異なるプロセス内に存在している
OLE がクライアントからオブジェクトへの呼び出しをリモート化
OLE は、クライアントとサーバーの間に入って、標準のマーシャリングと RPC を使って、異なるスレッディング モデルが相互運用を行うためのコードを提供
シングル スレッド オブジェクトが複数のフリー スレッド クライアントから同時に呼び出された場合、OLE はサーバーのメッセージ キューに、これらの呼び出しに対応するウィンドウ メッセージを入れることによって呼び出しを同期
オブジェクトのアパートメントは、メッセージの取り出しとディスパッチを行いながら、呼び出しを一度に 1 つずつ受け取る
スレッド セーフ
特定のスレッドを対象としているメッセージがそのスレッドだけに到着
インプロセス サーバー
...