Delphiのスレッドクラス
ラプター[メンタルスタジオ]
http://mental.mentsu.com
(1つ)
Delphi には、マルチスレッド プログラミングを実装するために使用されるスレッド クラス TThread があります。ほとんどの Delphi 書籍では、TThread クラスのいくつかのメンバーについて簡単に紹介し、次に Execute 関数について説明します。の同期が完了しました。ただし、これがマルチスレッド プログラミングのすべてではありません。この記事を書く目的はこれを補足することです。
スレッドは本質的に、プロセス内で同時に実行されるコードの一部です。プロセスには少なくとも 1 つのスレッド (いわゆるメイン スレッド) があります。同時に複数のサブスレッドが存在することもできます。プロセス内で複数のスレッドが使用されることを「マルチスレッド」と呼びます。
では、このいわゆる「コードの一部」はどのように定義されるのでしょうか?実際、これは (Delphi の) 関数またはプロセスです。
Windows API を使用してスレッドを作成する場合、スレッドは CreateThread という API 関数を通じて実装されます。この関数は次のように定義されます。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes、
DWord dwStackSize、
LPTHREAD_START_ROUTINE lpStartAddress、
LPVOID lpパラメータ、
DWORD dwCreationFlags、
LPDWORD lpThreadId
);
パラメータはその名の通り、スレッド属性 (NT ではスレッド セキュリティ属性を設定するために使用され、9X では無効)、スタック サイズ、開始アドレス、パラメータ、作成フラグ (スレッドの作成時の状態を設定するために使用)、スレッド ID、最後にスレッドハンドルを返します。開始アドレスはスレッド関数の入り口であり、スレッド関数が終了するまでスレッドは終了します。
スレッド全体の実行プロセスは次のとおりです。
CreateThread には多くのパラメーターがあり、Windows API であるため、一般的なスレッド関数が C ランタイム ライブラリで提供されています (理論的には、スレッドをサポートするすべての OS で使用できます)。
unsigned long _beginthread(void (_USERENTRY *__start)(void *), unsigned __stksize, void *__arg);
Delphi も、同じ機能を持つ同様の関数を提供します。
function BeginThread(SecurityAttributes: ポインタ; StackSize: LongWord; ThreadFunc: TThreadFunc; パラメータ: ポインタ; CreationFlags: LongWord; var ThreadId: LongWord): Integer;
これら 3 つの関数の機能は基本的に同じであり、スレッド関数のコードを独立したスレッドに配置して実行します。スレッド関数と一般関数の最大の違いは、スレッド関数が開始されるとすぐに 3 つのスレッド起動関数が下向きに実行され続けるのに対し、スレッド関数は独立したスレッドで実行されることです。実行にかかる? それが返されると、メインスレッドは気にせず、知りません。
通常の状況では、スレッド関数が戻った後、スレッドは終了します。しかし、他の方法もあります。
Windows API:
VOID ExitThread(DWORD dwExitCode);
C ランタイム ライブラリ:
void _endthread(void);
Delphi ランタイム ライブラリ:
PROcedure EndThread(ExitCode: Integer);
必要なスレッド データ (ステータス/プロパティなど) を記録するために、OS はスレッドの内部オブジェクトを作成します。たとえば、Windows では、ハンドルはこの内部オブジェクトのハンドルであるため、このオブジェクトを解放する必要があります。スレッドが終了したとき。
マルチスレッド プログラミングは API または RTL (ランタイム ライブラリ) を使用して簡単に実行できますが、さらに詳細な処理が必要となるため、Delphi はクラス単位でスレッドをより適切にカプセル化しました。これが VCL スレッド クラスです。
このクラスの使用も非常に簡単です。ほとんどの Delphi の書籍では、基本的な使用法は次のとおりであると記載されています。まず、TThread から独自のスレッド クラスを派生し(TThread は抽象クラスであり、インスタンスを生成できないため)、次に Override 抽象メソッドを使用します。 Execute( Thisはスレッド関数であり、スレッド内で実行されるコードの一部です) ビジュアル VCL オブジェクトを使用する必要がある場合は、同期プロセスを通じて実行する必要があります。具体的な内容についてはここでは割愛しますので関連書籍を参照してください。
この記事で次に説明するのは、TThread クラスがスレッドをカプセル化する方法、つまり TThread クラスの実装について詳しく説明することです。なぜなら、それを真に理解することによってのみ、それをより良く使用できるからです。
以下は DELPHI7 の TThread クラスの宣言です (この記事では Windows プラットフォームでの実装のみについて説明しているため、Linux プラットフォームに関連するコードはすべて削除されています)。
TThread = クラス
プライベート
Fハンドル: Tハンドル;
FThreadID: THandle;
FCreateSuspended: ブール値;
FTerminated: ブール値。
FSuspended: ブール値。
FFreeOnTerminate: ブール値;
FFinished: ブール値。
FReturnValue: 整数;
FOnTerminate: TNotifyEvent;
FSynchronize: TSynchronizeRecord;
FFatalException: TObject;
プロシージャ CallOnTerminate;
クラス プロシージャ Synchronize(ASyncRec: PSynchronizeRecord);
関数 GetPriority: TThreadPriority;
プロシージャ SetPriority(値: TThreadPriority);
プロシージャ SetSuspended(値: ブール値);
保護された
プロシージャ CheckThreadError(ErrCode: 整数);
プロシージャ CheckThreadError(Success: Boolean);
プロシージャ DoTerminate;
プロシージャ 仮想を実行します。
プロシージャ Synchronize(メソッド: TThreadMethod);
property ReturnValue: 整数 読み取り FReturnValue 書き込み FReturnValue;
property Terminated: ブール値読み取り FTerminated;
公共
コンストラクター Create(CreateSuspended: Boolean);
デストラクタ オーバーライド;
プロシージャ AfterConstruction をオーバーライドします。
手順を再開します。
手順を一時停止します。
手順を終了します。
関数 WaitFor: LongWord;
クラス プロシージャ Synchronize(AThread: TThread; AMethod: TThreadMethod);
クラス プロシージャ StaticSynchronize(AThread: TThread; AMethod: TThreadMethod);
プロパティ FatalException: TObject 読み取り FFatalException;
property FreeOnTerminate: ブール値読み取り FFreeOnTerminate 書き込み FFreeOnTerminate;
プロパティ ハンドル: THandle 読み取り FHandle;
property Priority: TThreadPriority 読み取り GetPriority 書き込み SetPriority;
property Suspended: ブール値読み取り FSuspended 書き込み SetSuspended;
プロパティ ThreadID: THandle 読み取り FThreadID;
プロパティ OnTerminate: TNotifyEvent 読み取り FOnTerminate 書き込み FOnTerminate;
終わり;
TThread クラスは Delphi の RTL の比較的単純なクラスであり、クラス メンバーはそれほど多くなく、クラス属性は非常に単純かつ明確です。この記事では、いくつかの重要なクラス メンバー メソッドと唯一のイベント OnTerminate についてのみ詳細に分析します。 。
(つづく)