C#のマルチスレッド
スレッドは 、プログラムの実行パスとして定義されます。各スレッドは、コントロールの一意のフローを定義します。 アプリケーションが複雑で時間のかかる操作を必要とする場合は、別の実行パスを設定することはしばしば有用スレッドで、各スレッドは、特定のジョブを実行します。
スレッドは軽量プロセスです。 一般的な例は、最新のオペレーティングシステム実装の並列プログラミングでスレッドを使用することです。 アプリケーションの効率を向上させながら、廃棄物のCPUサイクルを節約するスレッドを使用してください。
これまでは、プログラムはシングルスレッドのアプリケーションのインスタンスが実行されているとして実行するように単一のプロセスで用意しました。 しかし、このようなアプリケーションでのみ、同時に一つのタスクを実行することができます。 同時に複数のタスクを実行するために、より小さなスレッドに分割することができます。
スレッドのライフサイクル
スレッドのライフサイクルが終了終了または実行スレッド内に完了し、System.Threading.Threadクラス・オブジェクトが作成され始めます。
以下は、スレッドのライフサイクルの状態を示しています。
- スレッドのインスタンスが作成されると、しかし、この方法は、スタート条件と呼ばれていません:状態は起動しません 。
- レディ状態:スレッドがCPUサイクルと条件を待っているときに実行する準備ができています。
- 非動作状態:次のような状況は、スレッドの下で実行されていません。
- この方法は、スリープと呼ばれてきました
- この方法は、ウェイトと呼ばれてきました
- I / O操作を妨害することにより
- 死のステータス:スレッドが実行または中断された状態時を完了しました。
メインスレッド
スレッドの作業のためのC#では、System.Threading.Threadクラス。 それはあなたがシングルスレッドでマルチスレッドアプリケーションを作成し、アクセスすることができます。 実行されるプロセスの最初のスレッドは、プライマリスレッドと呼ばれています。
C#のプログラムが実行を開始すると、メインスレッドが自動的に作成されます。 スレッドを作成するために、Threadクラスを使用して、メインスレッドの子スレッドと呼ばれています。 あなたは、ThreadクラスCurrentThreadプロパティアクセスのスレッドを使用することができます。
次のプログラムは、メインスレッドの実行を示しています。
システムを用いました。 System.Threadingを使用して、 名前空間MultithreadingApplication { クラスMainThreadProgram { 静的な無効メイン(文字列[] args) { =にThread.currentThread番目のスレッド。 th.Name = "MainThread"; Console.WriteLineを(、th.Name「これは{0}です "); Console.ReadKey()。 } } }
上記のコードはコンパイルされ、実行されると、次の結果を生成します。
これはMainThreadです
Threadクラス共通の属性とメソッド
次の表は、Threadクラスにいくつかの共通の属性を示しています 。
属性 | 描述 |
---|---|
CurrentContext | 获取线程正在其中执行的当前上下文。 |
CurrentCulture | 获取或设置当前线程的区域性。 |
CurrentPrinciple | 获取或设置线程的当前负责人(对基于角色的安全性而言)。 |
CurrentThread | 获取当前正在运行的线程。 |
CurrentUICulture | 获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。 |
ExecutionContext | 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。 |
IsAlive | 获取一个值,该值指示当前线程的执行状态。 |
IsBackground | 获取或设置一个值,该值指示某个线程是否为后台线程。 |
IsThreadPoolThread | 获取一个值,该值指示线程是否属于托管线程池。 |
ManagedThreadId | 获取当前托管线程的唯一标识符。 |
Name | 获取或设置线程的名称。 |
Priority | 获取或设置一个值,该值指示线程的调度优先级。 |
ThreadState | 获取一个值,该值包含当前线程的状态。 |
次の表は、一般的に使用されるいくつかのメソッド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() 通知主机托管代码将要执行依赖于当前物理操作系统线程的标识的指令。 |
6 | public static void EndCriticalRegion() 通知主机执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常仅影响当前任务。 |
7 | public static void EndThreadAffinity() 通知主机托管代码已执行完依赖于当前物理操作系统线程的标识的指令。 |
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() 取消为当前线程请求的 Abort。 |
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クラスは、子スレッドを開始するためにスタート()メソッドを呼び出します。
次のプログラムは、この概念を示しています。
システムを用いました。 System.Threadingを使用して、 名前空間MultithreadingApplication { クラスThreadCreationProgram { 公共の静的な無効CallToChildThread() { Console.WriteLineを(「子供のスレッドが開始 "); } 静的な無効メイン(文字列[] args) { ThreadStart childref =新しいThreadStart(CallToChildThread)。 Console.WriteLineを( "メインで:子スレッドの作成」を参照)。 スレッドchildThread =新しいスレッド(childref)。 childThread.Start()。 Console.ReadKey()。 } } }
上記のコードはコンパイルされ、実行されると、次の結果を生成します。
主に:子スレッドの作成 子スレッドの開始
スレッドの管理
スレッドThreadクラスは、管理の様々な方法を提供します。
次の例では、特定のタイムアウトのスレッドで使用されているスリープ()メソッドの使用方法を示します。
システムを用いました。 System.Threadingを使用して、 名前空間MultithreadingApplication { クラスThreadCreationProgram { 公共の静的な無効CallToChildThread() { Console.WriteLineを(「子供のスレッドが開始 "); //スレッドはint型sleepfor = 5000 5000ミリ秒に中断されます。 Console.WriteLineを(「子スレッドは{0}秒間一時停止しました」、 sleepfor / 1000); Thread.sleep(sleepfor)。 Console.WriteLineを(「子供のスレッドが再開されます "); } 静的な無効メイン(文字列[] args) { ThreadStart childref =新しいThreadStart(CallToChildThread)。 Console.WriteLineを( "メインで:子スレッドの作成」を参照)。 スレッドchildThread =新しいスレッド(childref)。 childThread.Start()。 Console.ReadKey()。 } } }
上記のコードはコンパイルされ、実行されると、次の結果を生成します。
主に:子スレッドの作成 子スレッドの開始 子スレッドは5秒間一時停止します 子スレッドが再開
スレッドを破棄
アボート()メソッドは、スレッドを破壊するために使用されます。
ThreadAbortExceptionのをスローすることによって、実行時にスレッドを中止します。finallyブロック、制御はブロックし、最終的に送信される場合には、この例外は、キャッチすることができません。
次のプログラムは、この点を示しています。
システムを用いました。 System.Threadingを使用して、 名前空間MultithreadingApplication { クラスThreadCreationProgram { 公共の静的な無効CallToChildThread() { 試します { Console.WriteLineを(「子供のスレッドが開始 "); // 10まで数えます 以下のための(int型のカウンタ= 0;カウンタ<= 10;カウンター++) { Thread.sleep(500)。 Console.WriteLineを(カウンタ)。 } Console.WriteLineを(「子スレッドが完了します "); } キャッチ(ThreadAbortExceptionの電子) { Console.WriteLineを(「スレッド中止例外 "); } 最終的に { Console.WriteLineを(「スレッドの例外をキャッチできませんでした "); } } 静的な無効メイン(文字列[] args) { ThreadStart childref =新しいThreadStart(CallToChildThread)。 Console.WriteLineを( "メインで:子スレッドの作成」を参照)。 スレッドchildThread =新しいスレッド(childref)。 childThread.Start()。 //いくつかの時間のThread.sleep(2000)のためにメインスレッドを停止します。 //ここで停止状態の子スレッドConsole.WriteLineを( "メインで:子スレッドの中止"); childThread.Abort()。 Console.ReadKey()。 } } }
上記のコードはコンパイルされ、実行されると、次の結果を生成します。
主に:子スレッドの作成 子スレッドの開始 0 1 2 主に:子スレッドを中止 スレッドアボート例外 スレッドの例外をキャッチできませんでした。