C# Thread 생성

  • System.Threading.Thread 클래스

  • Thread 클래스의 생성자(Constructor)에 실행하고자 하는 메소드를 델리게이트로 지정한 후, Thread 클래스 객체에서 Start() 메소드를 호출하면 새로운 쓰레드가 생성되어 실행된다.

  • namespace MultiThrdApp
    {
        using System;
        using System.Threading;
      
        class Program
        {
            static void Main(string[] args)
            {
                new Program().DoTest();
            }
      
            void DoTest()
            {
                // 새로운 쓰레드에서 Run() 실행
                Thread t1 = new Thread(new ThreadStart(Run));
                t1.Start();
      
                // 메인쓰레드에서 Run() 실행
                Run();         
            }
      
            // 출력
            // Thread#1: Begin
            // Thread#3: Begin
            // Thread#1: End
            // Thread#3: End
      
            void Run()
            {
                Console.WriteLine("Thread#{0}: Begin", Thread.CurrentThread.ManagedThreadId);
                // Do Something
                Thread.Sleep(3000);
                Console.WriteLine("Thread#{0}: End", Thread.CurrentThread.ManagedThreadId);
            }
        }
    }
    

Thread 다른 예제

class Program
{
    static void Main(string[] args)
    {            
        // Run 메서드를 입력받아
        // ThreadStart 델리게이트 타입 객체를 생성한 후
        // Thread 클래스 생성자에 전달
        Thread t1 = new Thread(new ThreadStart(Run));           
        t1.Start();
            
        // 컴파일러가 Run() 메서드의 함수 프로토타입으로부터
        // ThreadStart Delegate객체를 추론하여 생성함
        Thread t2 = new Thread(Run);
        t2.Start();

        // 익명메서드(Anonymous Method)를 사용하여
        // 쓰레드 생성
        Thread t3 = new Thread(delegate()
        {
            Run();
        });
        t3.Start();

        // 람다식 (Lambda Expression)을 사용하여
        // 쓰레드 생성
        Thread t4 = new Thread(() => Run());
        t4.Start();

        // 간략한 표현
        new Thread(() => Run()).Start();
    }

    static void Run()
    {
        Console.WriteLine("Run");
    }
}

다른 클래스 메소드 Thread 사용

  • 다른 클래스를 쓰레드에 호출하기 위해서는 객체를 생성한 후 그 객체의 메소드를 델리게이트로 Thread에 전달하면 된다.

  • class Helper
    {
        public void Run()
        {
            Console.WriteLine("Helper.Run");
        }
    }
      
    class Program
    {
        static void Main(string[] args)
        {
            // Helper클래스의 Run메서드 호출
            Helper obj = new Helper();
            Thread t = new Thread(obj.Run);
            t.Start();
        }
    }
    

Thread 클래스 파라미터 전달

  • 파라미터 전달 X : ThreadStart 델리게이트 사용

  • 파라미터 전달 O : ParameterizedThreadStart 델리게이트 사용

  • class Program
    {
        static void Main(string[] args)
        {
            // 파라미터 없는 ThreadStart 사용
            Thread t1 = new Thread(new ThreadStart(Run));
            t1.Start();
      
            // ParameterizedThreadStart 파라미터 전달
            // Start()의 파라미터로 radius 전달
            Thread t2 = new Thread(new ParameterizedThreadStart(Calc));
            t2.Start(10.00);
              
            // ThreadStart에서 파라미터 전달
            Thread t3 = new Thread(() => Sum(10, 20, 30));
            t3.Start();
        }
      
        static void Run()
        {
            Console.WriteLine("Run");
        }
      
        // radius라는 파라미터를 object 타입으로 받아들임
        static void Calc(object radius)
        {
            double r = (double)radius;
            double area = r * r * 3.14;
            Console.WriteLine("r={0},area={1}", r, area);
        }
      
        static void Sum(int d1, int d2, int d3)
        {
            int sum = d1 + d2 + d3;
            Console.WriteLine(sum);
        }
    }
    

Background 쓰레드 vs Foreground 쓰레드

  • Thread 클래스 객체를 생성한 후 Start()를 실행하기 전에 IsBackground 속성을 True/False로 지정할 수 있다.

  • True로 지정하면 백그라운드 쓰레드가 된다.

  • 디폴트 값은 False, (= Foreground 쓰레드)

  • Foreground 쓰레드는 메인 쓰레드가 종료되더라도 Foreground 쓰레드가 살아 있는 한, 프로세스가 종료되지 않고 계속 실행된다.

  • Background 쓰레드는 메인 쓰레드가 종료되면 프로세스를 종료된다.

  • // Foreground 쓰레드
    Thread t1 = new Thread(new ThreadStart(Run));            
    t1.Start();
                  
    // 백그라운드 쓰레드
    Thread t2 = new Thread(new ThreadStart(Run));
    t2.IsBackground = true;
    t2.Start();