C# - マルチスレッド
スレッド プログラムの実行パスとして定義されます。各スレッドは、固有の制御フローを定義します。アプリケーションに複雑で時間のかかる操作が含まれる場合、各スレッドが特定のジョブを実行するように、異なる実行パスまたはスレッドを設定すると役立つことがよくあります。
スレッドは軽量プロセスです .スレッドの一般的な使用例の 1 つは、最新のオペレーティング システムによる並行プログラミングの実装です。スレッドを使用することで、CPU サイクルの無駄を省き、アプリケーションの効率を高めます。
これまでのところ、アプリケーションの実行中のインスタンスである単一のプロセスとして単一のスレッドが実行されるプログラムを作成しました。ただし、この方法では、アプリケーションは一度に 1 つのジョブを実行できます。一度に複数のタスクを実行するには、小さなスレッドに分割できます。
スレッドのライフサイクル
スレッドのライフサイクルは、System.Threading.Thread クラスのオブジェクトが作成されたときに開始され、スレッドが終了または実行を完了したときに終了します。
以下は、スレッドのライフサイクルにおけるさまざまな状態です −
-
未開始状態 − スレッドのインスタンスは作成されているが、Start メソッドが呼び出されていない状況です。
-
準備完了状態 − スレッドが実行可能で、CPU サイクルを待機している状態です。
-
実行不可状態 − 次の場合、スレッドは実行可能ではありません
- Sleep メソッドが呼び出されました
- Wait メソッドが呼び出されました
- I/O 操作によってブロックされています
-
デッドステート − スレッドが実行を完了または中止したときの状況です。
メイン スレッド
C# では、System.Threading.Thread クラスは、スレッドを操作するために使用されます。マルチスレッド アプリケーションで個々のスレッドを作成し、アクセスすることができます。プロセスで実行される最初のスレッドは、メインと呼ばれます
C# プログラムの実行が開始されると、メイン スレッドが自動的に作成されます。 Thread を使用して作成されたスレッド クラスは、メイン スレッドの子スレッドと呼ばれます。 CurrentThread を使用してスレッドにアクセスできます Thread クラスのプロパティ。
次のプログラムは、メイン スレッドの実行を示しています −
ライブデモusing System; using System.Threading; namespace MultithreadingApplication { class MainThreadProgram { static void Main(string[] args) { Thread th = Thread.CurrentThread; th.Name = "MainThread"; Console.WriteLine("This is {0}", th.Name); Console.ReadKey(); } } }
上記のコードをコンパイルして実行すると、次の結果が生成されます −
This is MainThread
Thread クラスのプロパティとメソッド
次の表は、最も一般的に使用されるいくつかのプロパティを示しています スレッドの クラス−
Sr.No. | プロパティと説明 |
---|---|
1 | 現在のコンテキスト スレッドが実行されている現在のコンテキストを取得します。 |
2 | 現在の文化 現在のスレッドのカルチャを取得または設定します。 |
3 | 現在の原則 スレッドの現在のプリンシパルを取得または設定します (ロールベースのセキュリティ用)。 |
4 | 現在のスレッド 現在実行中のスレッドを取得します。 |
5 | 現在のUICulture Resource Manager が実行時にカルチャ固有のリソースを検索するために使用する現在のカルチャを取得または設定します。 |
6 | 実行コンテキスト 現在のスレッドのさまざまなコンテキストに関する情報を含む ExecutionContext オブジェクトを取得します。 |
7 | IsAlive 現在のスレッドの実行ステータスを示す値を取得します。 |
8 | IsBackground スレッドがバックグラウンド スレッドかどうかを示す値を取得または設定します。 |
9 | IsThreadPoolThread スレッドがマネージド スレッド プールに属しているかどうかを示す値を取得します。 |
10 | ManagedThreadId 現在のマネージド スレッドの一意の識別子を取得します。 |
11 | 名前 スレッドの名前を取得または設定します。 |
12 | 優先 スレッドのスケジューリング優先度を示す値を取得または設定します。 |
13 | スレッド状態 現在のスレッドの状態を含む値を取得します。 |
次の表は、最も一般的に使用される方法の一部を示しています。 スレッドの クラス−
Sr.No. | 方法と説明 |
---|---|
1 | public void Abort() 呼び出されたスレッドで ThreadAbortException を発生させ、スレッドを終了するプロセスを開始します。通常、このメソッドを呼び出すと、スレッドが終了します。 |
2 | public static LocalDataStoreSlot AllocateDataSlot() すべてのスレッドに名前のないデータ スロットを割り当てます。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。 |
3 | public static LocalDataStoreSlot AllocateNamedDataSlot(string name) すべてのスレッドに名前付きデータ スロットを割り当てます。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。 |
4 | public static void BeginCriticalRegion() 実行がコードの領域に入ろうとしていることをホストに通知します。この領域では、スレッドの中止または未処理の例外の影響により、アプリケーション ドメイン内の他のタスクが危険にさらされる可能性があります。 |
5 | public static void BeginThreadAffinity() マネージド コードが現在の物理オペレーティング システム スレッドの ID に依存する命令を実行しようとしていることをホストに通知します。 |
6 | public static void EndCriticalRegion() スレッド アボートまたは未処理の例外の影響が現在のタスクに限定されるコード領域に実行が入ることをホストに通知します。 |
7 | public static void EndThreadAffinity() マネージ コードが現在の物理オペレーティング システム スレッドの ID に依存する命令の実行を終了したことをホストに通知します。 |
8 | public static void FreeNamedDataSlot(文字列名) プロセス内のすべてのスレッドについて、名前とスロットの間の関連付けを削除します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。 |
9 | public static Object GetData(LocalDataStoreSlot スロット) 現在のスレッドの現在のドメイン内で、現在のスレッドの指定されたスロットから値を取得します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。 |
10 | public static AppDomain GetDomain() 現在のスレッドが実行されている現在のドメインを返します。 |
11 | public static AppDomain GetDomainID() 一意のアプリケーション ドメイン識別子を返します |
12 | public static LocalDataStoreSlot GetNamedDataSlot(string name) 名前付きデータ スロットを検索します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。 |
13 | public void Interrupt() WaitSleepJoin スレッド状態にあるスレッドを中断します。 |
14 | public void Join() 標準の COM および SendMessage ポンピングの実行を継続しながら、スレッドが終了するまで呼び出し元のスレッドをブロックします。このメソッドにはさまざまなオーバーロード形式があります。 |
15 | public static void MemoryBarrier() 次のようにメモリ アクセスを同期します。現在のスレッドを実行しているプロセッサは、MemoryBarrier の呼び出しの前のメモリ アクセスが、MemoryBarrier の呼び出しに続くメモリ アクセスの後に実行されるような方法で命令を並べ替えることができません。 |
16 | public static void ResetAbort() 現在のスレッドに対して要求された中止をキャンセルします。 |
17 | public static void SetData(LocalDataStoreSlot スロット、オブジェクト データ) そのスレッドの現在のドメインに対して、現在実行中のスレッドの指定されたスロットにデータを設定します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。 |
18 | public void Start() スレッドを開始します。 |
19 | public static void Sleep(int millisecondsTimeout) スレッドを一定期間一時停止します。 |
20 | public static void SpinWait(int iterations) iterations パラメータで定義された回数だけスレッドを待機させます |
21 | public static byte VolatileRead(ref byte address) public static double VolatileRead(ref double address) public static int VolatileRead(ref int address) public static Object VolatileRead(参照オブジェクト アドレス) フィールドの値を読み取ります。この値は、プロセッサの数やプロセッサ キャッシュの状態に関係なく、コンピューター内の任意のプロセッサによって書き込まれた最新の値です。このメソッドには、さまざまなオーバーロード形式があります。上記は一部のみです。 |
22 | public static void VolatileWrite(ref バイト アドレス,バイト値) public static void VolatileWrite(ref double address, double value) public static void VolatileWrite(ref int address, int value) public static void VolatileWrite(参照オブジェクト アドレス、オブジェクト値) コンピューター内のすべてのプロセッサが値を認識できるように、値をフィールドにすぐに書き込みます。このメソッドには、さまざまなオーバーロード形式があります。上記は一部のみです。 |
23 | public static bool Yield() 呼び出し元のスレッドが、現在のプロセッサで実行する準備ができている別のスレッドに実行を譲るようにします。オペレーティング システムは、譲るスレッドを選択します。 |
スレッドの作成
スレッドは、Thread クラスを拡張することによって作成されます。次に、拡張された Thread クラスが Start() を呼び出します 子スレッドの実行を開始するメソッド。
次のプログラムは、概念を示しています −
ライブデモusing System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { public static void CallToChildThread() { Console.WriteLine("Child thread starts"); } static void Main(string[] args) { ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); Thread childThread = new Thread(childref); childThread.Start(); Console.ReadKey(); } } }
上記のコードをコンパイルして実行すると、次の結果が生成されます −
In Main: Creating the Child thread Child thread starts
スレッドの管理
Thread クラスは、スレッドを管理するためのさまざまなメソッドを提供します。
次の例は、sleep() の使用を示しています。 特定の期間、スレッドを一時停止させるメソッド。
ライブデモusing System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { public static void CallToChildThread() { Console.WriteLine("Child thread starts"); // the thread is paused for 5000 milliseconds int sleepfor = 5000; Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000); Thread.Sleep(sleepfor); Console.WriteLine("Child thread resumes"); } static void Main(string[] args) { ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); Thread childThread = new Thread(childref); childThread.Start(); Console.ReadKey(); } } }
上記のコードをコンパイルして実行すると、次の結果が生成されます −
In Main: Creating the Child thread Child thread starts Child Thread Paused for 5 seconds Child thread resumes
スレッドの破棄
Abort() メソッドはスレッドを破棄するために使用されます。
ランタイムは ThreadAbortException をスローしてスレッドを中止します .この例外はキャッチできません。コントロールは finally に送信されます もしあれば、ブロックしてください。
次のプログラムはこれを示しています −
ライブデモusing System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { public static void CallToChildThread() { try { Console.WriteLine("Child thread starts"); // do some work, like counting to 10 for (int counter = 0; counter <= 10; counter++) { Thread.Sleep(500); Console.WriteLine(counter); } Console.WriteLine("Child Thread Completed"); } catch (ThreadAbortException e) { Console.WriteLine("Thread Abort Exception"); } finally { Console.WriteLine("Couldn't catch the Thread Exception"); } } static void Main(string[] args) { ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); Thread childThread = new Thread(childref); childThread.Start(); //stop the main thread for some time Thread.Sleep(2000); //now abort the child Console.WriteLine("In Main: Aborting the Child thread"); childThread.Abort(); Console.ReadKey(); } } }
上記のコードをコンパイルして実行すると、次の結果が生成されます −
In Main: Creating the Child thread Child thread starts 0 1 2 In Main: Aborting the Child thread Thread Abort Exception Couldn't catch the Thread Exception
C言語