C# 多线程

线程プログラムの実行パスとして定義されます。各スレッドは独自の制御フローを定義します。アプリケーションが複雑で時間のかかる操作を伴う場合、異なるスレッド実行パスを設定することはしばしば有益であり、各スレッドが特定の作業を実行します。

スレッドは轻量级进程スレッドを使用する一般的な例は、現代のオペレーティングシステムにおける並列プログラミングの実装です。スレッドを使用することでCPUサイクルの無駄遣いを節約し、アプリケーションの効率を向上させます。

これまでに作成したプログラムは、単一のスレッドがアプリケーションの実行インスタンスとして単一のプロセスで実行されるものでした。しかし、これではアプリケーションは同時に1つのタスクしか実行できません。複数のタスクを同時に実行するために、アプリケーションをより小さなスレッドに分割することができます。

スレッドライフサイクル

スレッドのライフサイクルは、System.Threading.Thread クラスのオブジェクトが作成されたときに始まり、スレッドが終了するか実行が完了したときに終わります。

以下に、スレッドのライフサイクルにおけるさまざまな状態を示します:

  • 未启动状态:スレッドインスタンスが作成されたが、Startメソッドが呼び出されていない状態。
  • 就绪状态:スレッドが実行の準備ができており、CPUサイクルを待機している状態。
  • 不可运行状态:以下のいくつかの状況では、スレッドは実行可能ではありません:
    • すでに Sleep メソッドを呼び出した
    • すでに Wait メソッドを呼び出した
    • I/O 操作によってブロックされる
  • 死亡状态:スレッドが実行を完了したか、中止されたときの状態。

主线程

C# では、System.Threading.ThreadThread クラスはスレッドの作業に使用されます。これにより、マルチスレッドアプリケーション内の個々のスレッドを作成し、アクセスすることができます。プロセス内で最初に実行されるスレッドは、...と呼ばれます。主线程。

C# プログラムの実行が開始されると、メインスレッドが自動的に作成されます。使用ThreadThread クラスによって作成されたスレッドは、メインスレッドの子スレッドと呼ばれます。Thread クラスの...を使用できます。CurrentThread属性はスレッドにアクセスする。

以下のプログラムは、メインスレッドの実行を示しています:

实例

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 クラスの一般的に使用されるプロパティとメソッド

以下の表に一覧を示しますThreadクラスのいくつかの一般的な属性:

属性描述
CurrentContextスレッドが実行されている現在のコンテキストを取得します。
CurrentCulture現在のスレッドのカルチャを取得または設定します。
CurrentPrincipalスレッドの現在のプリンシパルを取得または設定します(ロールベースのセキュリティの場合)。
CurrentThread現在実行中のスレッドを取得する。
CurrentUICultureリソースマネージャーが実行時にカルチャ固有のリソースを検索するために使用する現在のカルチャを取得または設定します。
ExecutionContext現在のスレッドに関するさまざまなコンテキスト情報を含む ExecutionContext オブジェクトを取得します。
IsAlive現在のスレッドの実行状態を示す値を取得します。
IsBackgroundスレッドがバックグラウンドスレッドであるかどうかを示す値を取得または設定します。
IsThreadPoolThreadスレッドがマネージドスレッドプールに属しているかどうかを示す値を取得します。
ManagedThreadId現在のマネージドスレッドの一意の識別子を取得します。
Nameスレッドの名前を取得または設定します。
Priorityスレッドのスケジューリング優先順位を示す値を取得または設定します。
ThreadState現在のスレッドの状態を含む値を取得します。

以下の表に一覧を示しますThreadクラスのいくつかの一般的な方法:

序号メソッド名 & 説明
1public void Abort()
このメソッドを呼び出したスレッド上で ThreadAbortException を発生させ、このスレッドを終了するプロセスを開始します。このメソッドを呼び出すと、通常はスレッドが終了します。
2public static LocalDataStoreSlot AllocateDataSlot()
すべてのスレッドに名前のないデータスロットを割り当てます。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。
3public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
すべてのスレッドに名前付きデータスロットを割り当てます。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。
4public static void BeginCriticalRegion()
ホストに、実行がコード領域に入ろうとしていることを通知します。そのコード領域では、スレッドの中止または未処理の例外の影響が、アプリケーションドメイン内の他のタスクに害を及ぼす可能性があります。
5public static void BeginThreadAffinity()
ホストに、マネージドコードが現在の物理オペレーティングシステムスレッドの ID に依存する命令を実行しようとしていることを通知します。
6public static void EndCriticalRegion()
ホストに、実行がコード領域に入ろうとしていることを通知します。そのコード領域では、スレッドの中止または未処理の例外が現在のタスクのみに影響します。
7public static void EndThreadAffinity()
ホストに、マネージドコードが現在の物理オペレーティングシステムスレッドの ID に依存する命令の実行を完了したことを通知します。
8public static void FreeNamedDataSlot(string name)
プロセス内のすべてのスレッドについて、名前とスロットの間の関連付けを解除します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。
9public static Object GetData( LocalDataStoreSlot slot )
現在のスレッドの現在のドメイン内で、現在のスレッド上の指定されたスロットから値を取得します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。
10public static AppDomain GetDomain()
現在のスレッドが実行されている現在のドメインを返します。
11public static AppDomain GetDomainID()
一意のアプリケーションドメイン識別子を返します。
12public static LocalDataStoreSlot GetNamedDataSlot( string name )
名前付きデータスロットを検索します。パフォーマンスを向上させるには、代わりに ThreadStaticAttribute 属性でマークされたフィールドを使用してください。
13public void Interrupt()
WaitSleepJoin スレッド状態にあるスレッドを中断します。
14public void Join()
標準の COM および SendMessage メッセージポンプ処理を継続しながら、呼び出しスレッドを、あるスレッドが終了するまでブロックします。このメソッドにはさまざまなオーバーロード形式があります。
15public static void MemoryBarrier()
次のようにメモリアクセスを同期します:現在のスレッドを実行しているプロセッサは、命令を並べ替える際に、MemoryBarrier 呼び出しの後のメモリアクセスを、MemoryBarrier 呼び出しの前のメモリアクセスよりも先に実行する方式を採用することはできません。
16public static void ResetAbort()
現在のスレッドに対して要求された Abort をキャンセルします。
17public static void SetData( LocalDataStoreSlot slot, Object data )
現在実行中のスレッド上で、このスレッドの現在のドメインの指定されたスロットにデータを設定します。より良いパフォーマンスを得るには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用してください。
18public void Start()
スレッドを開始する。
19public static void Sleep( int millisecondsTimeout )
スレッドを一定時間一時停止させます。
20public static void SpinWait( int iterations )
スレッドに、iterations パラメータで定義された時間だけ待機させます。
21public 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 )

フィールド値を読み取ります。プロセッサの数やプロセッサキャッシュの状態に関係なく、この値はコンピュータの任意のプロセッサによって書き込まれた最新の値です。このメソッドにはさまざまなオーバーロード形式があります。ここではいくつかの形式のみを示します。
22public 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 )

値をフィールドに即座に書き込み、その値がコンピュータ内のすべてのプロセッサから見えるようにします。このメソッドにはさまざまなオーバーロード形式があります。ここでは一部の形式のみを示します。
23public 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");
            // 线程暂停 5000 毫秒
            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ブロックがある場合、制御はfinally块。

次のプログラムはこれを示しています:

实例

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            try
            {

                Console.WriteLine("Child thread starts");
                // 计数到 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();
            // 停止主线程一段时间
            Thread.Sleep(2000);
            // 現在子スレッドを中止する
            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 
其他扩展