C# 튜토리얼login
C# 튜토리얼
작가:php.cn  업데이트 시간:2022-04-11 14:06:23

C# 멀티스레딩



Thread은 프로그램의 실행 경로로 정의됩니다. 각 스레드는 고유한 제어 흐름을 정의합니다. 애플리케이션에 복잡하고 시간이 많이 걸리는 작업이 포함된 경우 각 스레드가 특정 작업을 수행하도록 서로 다른 스레드 실행 경로를 설정하는 것이 유용한 경우가 많습니다.

스레드는 경량 프로세스입니다. 스레드 사용의 일반적인 예는 최신 운영 체제에서 병렬 프로그래밍을 구현하는 것입니다. 스레드를 사용하면 낭비되는 CPU 주기를 절약하는 동시에 애플리케이션 효율성을 높일 수 있습니다.

지금까지 우리가 작성한 프로그램은 실행 중인 애플리케이션 인스턴스의 단일 프로세스로 실행되는 단일 스레드입니다. 그러나 이 하위 애플리케이션은 한 번에 하나의 작업만 수행할 수 있습니다. 여러 작업을 동시에 수행하기 위해 더 작은 스레드로 나눌 수 있습니다.

스레드 수명 주기

스레드 수명 주기는 System.Threading.Thread 클래스의 개체가 생성될 때 시작되고 스레드가 종료되거나 실행이 완료되면 끝납니다.

스레드 수명 주기의 다양한 상태는 다음과 같습니다.

  • Unstarted 상태: 스레드 인스턴스가 생성되었지만 Start 메서드가 호출되지 않은 상황.

  • Ready state: 스레드가 실행 준비가 되어 CPU 주기를 기다리는 상태입니다.

  • Unrunnable 상태: 다음 상황에서는 스레드를 실행할 수 없습니다.


    • Sleep 메소드가 호출되었습니다.

    • Wait 메소드가 호출되었습니다.

    • Th 거친 나/ O 작업 차단

  • 죽음 상태 : 스레드가 실행을 완료했거나 중단되었을 때의 조건입니다.

Main Thread

C#에서는 System.Threading.Thread 클래스가 스레드 작업에 사용됩니다. 다중 스레드 애플리케이션에서 개별 스레드를 생성하고 액세스할 수 있습니다. 프로세스에서 실행되는 첫 번째 스레드를 메인 스레드라고 합니다.

C# 프로그램이 실행되기 시작하면 메인 스레드가 자동으로 생성됩니다. Thread 클래스를 사용하여 생성된 스레드는 기본 스레드의 하위 스레드에 의해 호출됩니다. 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 클래스에서 일반적으로 사용되는 속성 및 메서드

다음 표는 다음과 같습니다. 스레드 클래스에서 일반적으로 사용되는 속성 :

PropertyDescription
CurrentContext스레드가 실행 중인 현재 컨텍스트를 가져옵니다.
CurrentCulture현재 스레드의 문화권을 가져오거나 설정합니다.
CurrentPrinciple스레드의 현재 주체를 가져오거나 설정합니다(역할 기반 보안의 경우).
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( 문자열 이름)
모든 스레드에 명명된 데이터 슬롯을 할당합니다. 성능을 향상하려면 대신 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 특성으로 표시된 필드를 사용하세요.
9공개 정적 개체 GetData( LocalDataStoreSlot 슬롯 )
현재 스레드의 현재 도메인에 있는 현재 스레드의 지정된 슬롯에서 값을 검색합니다. 성능을 향상하려면 대신 ThreadStaticAttribute 특성으로 표시된 필드를 사용하세요.
10public static AppDomain GetDomain()
현재 스레드가 실행 중인 현재 도메인을 반환합니다.
11public static AppDomain GetDomainID()
고유한 애플리케이션 도메인 식별자를 반환합니다.
12public static LocalDataStoreSlot GetNamedDataSlot( 문자열 이름 )
이름이 지정된 데이터 슬롯을 찾으세요. 성능을 향상하려면 대신 ThreadStaticAttribute 특성으로 표시된 필드를 사용하세요.
13public void Interrupt()
WaitSleepJoin 스레드 상태에서 스레드를 중단합니다.
14public void Join()
표준 COM 및 SendMessage 메시지 펌프 처리가 계속되는 동안 스레드 중 하나가 종료될 때까지 호출 스레드를 차단합니다. 이 메서드에는 다양한 오버로드가 있습니다.
15public static void MemoryBarrier()
다음과 같이 메모리 액세스를 동기화합니다. 현재 스레드 재정렬 명령을 실행하는 프로세서가 먼저 MemoryBarrier를 호출한 후 메모리 액세스를 사용할 수 없으며 그 이전에 메모리 액세스 방법을 사용합니다. MemoryBarrier 호출을 실행합니다.
16public static void ResetAbort()
현재 스레드에 대해 요청된 중단을 취소합니다.
17public static void SetData( LocalDataStoreSlot 슬롯, 객체 데이터 )
현재 실행 중인 스레드에서 이 스레드의 현재 도메인에 대해 지정된 슬롯에 데이터를 설정합니다. 성능을 향상하려면 대신 ThreadStaticAttribute 특성으로 표시된 필드를 사용하세요.
18public void Start()
스레드를 시작합니다.
19공개 정적 무효 수면( int 밀리초Timeout )
스레드를 잠시 멈춰주세요.
20public static void SpinWait( 정수 반복 )
스레드가 iterations 매개변수에 정의된 시간 동안 대기하도록 합니다.
21공개 정적 바이트 VolatileRead( 참조 바이트 주소 )
public static double VolatileRead( 참조 이중 주소 )
public static int VolatileRead( 참조 정수 주소 )
공용 정적 객체 VolatileRead( ref객체 주소 )

필드 값을 읽습니다. 이 값은 프로세서 수나 프로세서 캐시 상태에 관계없이 컴퓨터 프로세서에 의해 작성된 가장 최근 값입니다. 이 메서드에는 다양한 오버로드가 있습니다. 여기에는 일부 양식만 제공됩니다.
22public static void VolatileWrite( 참조 바이트 주소, 바이트 값 )
public static void VolatileWrite( 참조 이중 주소, 이중 값 )
public static void VolatileWrite( 참조 정수 주소, 정수 값 )
public static void VolatileWrite( 참조 객체 주소, 객체 가치 )

값이 컴퓨터의 모든 프로세서에 표시되도록 즉시 필드에 값을 씁니다. 이 메서드에는 다양한 오버로드가 있습니다. 여기에는 일부 양식만 제공됩니다.
23public static bool Yield()
호출 스레드가 현재 프로세서에서 실행할 준비가 된 다른 스레드를 실행하도록 합니다. 운영 체제는 실행할 스레드를 선택합니다.

Creating Threads

스레드는 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

Destroy the thread

Abort() 메소드를 사용하여 스레드를 파기합니다.

threadabortextception을 발생시켜 런타임 시 스레드를 중단합니다. 이 예외는 포착될 수 없습니다. 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

PHP 중국어 웹사이트