C#-マルチスレッド
A threadプログラムの実行パスとして定義されます。各スレッドは、固有の制御フローを定義します。アプリケーションに複雑で時間のかかる操作が含まれる場合は、各スレッドが特定のジョブを実行するように、異なる実行パスまたはスレッドを設定すると役立つことがよくあります。
スレッドは lightweight processes。スレッドの一般的な使用例の1つは、最新のオペレーティングシステムによる並行プログラミングの実装です。スレッドを使用すると、CPUサイクルの浪費が節約され、アプリケーションの効率が向上します。
これまで、単一のスレッドがアプリケーションの実行中のインスタンスである単一のプロセスとして実行されるプログラムを作成しました。ただし、この方法では、アプリケーションは一度に1つのジョブを実行できます。一度に複数のタスクを実行するために、小さなスレッドに分割することができます。
スレッドのライフサイクル
スレッドのライフサイクルは、System.Threading.Threadクラスのオブジェクトが作成されたときに始まり、スレッドが終了するか実行が完了すると終了します。
以下は、スレッドのライフサイクルにおけるさまざまな状態です。
The Unstarted State −スレッドのインスタンスが作成されたが、Startメソッドが呼び出されていない状況です。
The Ready State −スレッドを実行する準備ができてCPUサイクルを待機している状況です。
The Not Runnable State −スレッドが実行可能でない場合
- スリープメソッドが呼び出されました
- Waitメソッドが呼び出されました
- I / O操作によってブロックされました
The Dead State −スレッドが実行を完了するか中止される状況です。
メインスレッド
C#では、 System.Threading.Threadクラスはスレッドの操作に使用されます。マルチスレッドアプリケーションで個々のスレッドを作成してアクセスできます。プロセスで実行される最初のスレッドは、main 糸。
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
スレッドクラスのプロパティとメソッド
次の表に、最も一般的に使用されるものを示します。 properties の Thread クラス-
シニア番号 | プロパティと説明 |
---|---|
1 | CurrentContext スレッドが実行されている現在のコンテキストを取得します。 |
2 | CurrentCulture 現在のスレッドのカルチャを取得または設定します。 |
3 | CurrentPrinciple スレッドの現在のプリンシパルを取得または設定します(役割ベースのセキュリティ用)。 |
4 | CurrentThread 現在実行中のスレッドを取得します。 |
5 | CurrentUICulture 実行時にカルチャ固有のリソースを検索するためにリソースマネージャが使用する現在のカルチャを取得または設定します。 |
6 | ExecutionContext 現在のスレッドのさまざまなコンテキストに関する情報を含むExecutionContextオブジェクトを取得します。 |
7 | IsAlive 現在のスレッドの実行ステータスを示す値を取得します。 |
8 | IsBackground スレッドがバックグラウンドスレッドであるかどうかを示す値を取得または設定します。 |
9 | IsThreadPoolThread スレッドが管理対象スレッドプールに属しているかどうかを示す値を取得します。 |
10 | ManagedThreadId 現在の管理対象スレッドの一意の識別子を取得します。 |
11 | Name スレッドの名前を取得または設定します。 |
12 | Priority スレッドのスケジューリング優先度を示す値を取得または設定します。 |
13 | ThreadState 現在のスレッドの状態を含む値を取得します。 |
次の表は、最も一般的に使用されるもののいくつかを示しています methods の Thread クラス-
シニア番号 | 方法と説明 |
---|---|
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(string name) プロセス内のすべてのスレッドについて、名前とスロットの間の関連付けを排除します。パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用してください。 |
9 | public static Object GetData(LocalDataStoreSlot slot) 現在のスレッドの現在のドメイン内で、現在のスレッドの指定されたスロットから値を取得します。パフォーマンスを向上させるには、代わりに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 slot, Object data) そのスレッドの現在のドメインについて、現在実行中のスレッドの指定されたスロットにデータを設定します。パフォーマンスを向上させるには、代わりに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(ref Object address) フィールドの値を読み取ります。この値は、プロセッサの数やプロセッサキャッシュの状態に関係なく、コンピュータ内の任意のプロセッサによって書き込まれた最新のものです。このメソッドには、さまざまなオーバーロード形式があります。上記の一部のみを示します。 |
22 | public static void VolatileWrite(ref byte address,byte value) public static void VolatileWrite(ref double address, double value) public static void VolatileWrite(ref int address, int value) public static void VolatileWrite(ref Object address, Object value) 値をフィールドにすぐに書き込み、その値がコンピューター内のすべてのプロセッサーに表示されるようにします。このメソッドには、さまざまなオーバーロード形式があります。上記の一部のみを示します。 |
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