C# 스레드 Thread

728x90
  • 프로세스(Process)

- 실행 중인 프로그램

- 스케줄링 : 생성 -> 준비 -> 실행 -> 대기 ...-> 종료

- 멀티태스킹

 

  • 스레드(thread)

- OS가 CPU시간을 할당하는 기본 단위

- 하나 이상의 스레드로 구성

- 최적화 및 성능 향상의 장점이 있으나, 디버깅 이슈 등 구현이 어려움

- Context Switching 시 성능 저하 우려

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace _139_THREAD1
{
    class Program
    {
        static void RunThread(int index)
        {
            var sw = Stopwatch.StartNew();

            Console.WriteLine(string.Format("RunThread index : {0} Start", index));

            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("RunThread index : {0} sec : {1:N2}", index, sw.ElapsedMilliseconds / 1000.0f);
                Thread.Sleep(100);
            }
            Console.WriteLine(string.Format("RunThread index : {0} End", index));
            Console.WriteLine();
        }
        static void RunThread()
        {
            var sw = Stopwatch.StartNew();

            Console.WriteLine(string.Format("RunThread index : 0 Start"));

            for(int i = 0; i < 5; i++)
            {
                Console.WriteLine("RunThread index : {0} sec : {1:N2}", "0", sw.ElapsedMilliseconds / 1000.0f);
                Thread.Sleep(100);
            }
            Console.WriteLine(string.Format("RunThread index : 0 End"));
            Console.WriteLine();
        }
        static void RunThreadObject(object index)
        {
            var sw = Stopwatch.StartNew();

            Console.WriteLine(string.Format("RunThread index : {0} Start", index));

            for(int i = 0; i < 5; i++)
            {
                Console.WriteLine("RunThread index : {0} sec : {1:N2}", index, sw.ElapsedMilliseconds / 1000.0f);
                Thread.Sleep(100);
            }
            Console.WriteLine(string.Format("RunThread index : {0} End", index));
            Console.WriteLine();
        }
        static void Main(string[] args)
        {
            RunThread(); //기본 함수
            RunThread(1); //기본 함수
            RunThread(2); //기본 함수

            Thread _thread = new Thread(RunThread);
            _thread.Start();

            Console.WriteLine("====================================");
            Console.WriteLine();

            Thread _thread2 = new Thread(() => RunThread(1)); //delegate, 람다식
            _thread2.Start();

            new Thread(() => RunThread(2)).Start();

            Thread thread2 = new Thread(new ParameterizedThreadStart(RunThreadObject));
            thread2.Start(3); //매개변수를 갖는 스레드 실행하는 방법(object 매개변수만 넘길 수 있다)
        }
    }
}

 

  • 스레드 중단하기

1) Abort

 - 권장하지 않음

 - 함수의 종료를 보장하지 않기 때문에

2) Join

 - 함수의 종료를 보장

 - 동작 중인 함수의 끝까지 대기

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;

namespace _141_Thread_Abort_Join
{
    class Program
    {
        static void RunThread(int index)
        {
            DateTime start = DateTime.Now;
            var sw = Stopwatch.StartNew();

            Console.WriteLine(string.Format("RunThread index : {0} Start", index));

            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("RunThread index : {0} sec : {1:N2}", index, sw.ElapsedMilliseconds / 1000.0f);
                Thread.Sleep(100);
            }
            Console.WriteLine(string.Format("RunThread index : {0} End", index));
            Console.WriteLine();
        }
        static void RunException(int index)
        {
            DateTime start = DateTime.Now;
            var sw = Stopwatch.StartNew();

            Console.WriteLine(string.Format("RunThread index : {0} Start", index));

            try
            {
                for(int i = 0; i < 5; i++)
                {
                    Console.WriteLine("RunThread index : {0} sec : {1:N2}", index, sw.ElapsedMilliseconds / 1000.0f);
                    Thread.Sleep(100);
                }
                Console.WriteLine(string.Format("RunThread index : {0} End", index));
                Console.WriteLine();
            }
            catch(ThreadInterruptedException e)
            {
                //System.Threading.ThreadAbortException이라는 예외를 발생
                Console.WriteLine(e);
            }
            finally
            {
                Console.WriteLine("====  finally  ====");
            }
        }
        static void Main(string[] args)
        {
            Thread aa = new Thread(() => RunThread(0));
            aa.Start();
            Thread.Sleep(300);
            aa.Abort();
            Console.WriteLine(string.Format("Abort"));
            Console.WriteLine();

            Thread bb = new Thread(() => RunThread(1));
            bb.Start();
            Thread.Sleep(300);
            bb.Join();
            Console.WriteLine(string.Format("Join"));
            Console.WriteLine();

            Thread cc = new Thread(() => RunException(2));
            cc.Start();
            Thread.Sleep(300);
            //cc.Abort();
            cc.Interrupt();
            Console.WriteLine(string.Format("Interrupt"));
            Console.WriteLine();
        }
    }
}

 

  • 스레드 동기화(Thread Synchronization)

- 데이터 나 변수들을 공유하는 경우

- lock

- 데드락(DeadLock)

- Monitor, Mutex

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace _141_Thread_Synchronization
{
    class Program
    {
        static readonly object thisLock = new object();

        static int _index = 0;

        static void RunThread()
        {
            DateTime start = DateTime.Now;
            var sw = Stopwatch.StartNew();

            //크리티컬 섹션
            //lock 블록이 끝나기 전까지 다른 쓰레드는 이 코드를 실행 x
            lock(thisLock)
            {
                _index++;

                Console.WriteLine(string.Format("RunThread Start"));

                Console.WriteLine("RunThread 1 sec : {0:N2}", sw.ElapsedMilliseconds / 1000.0f);
                Thread.Sleep(100);

                Console.WriteLine(string.Format("RunThreadEnd"));
                Console.WriteLine("_index : " + _index);
            }
        }
        //_index 값을 순차적으로 증가
        static void Main(string[] args)
        {
            for(int i = 0; i < 10; i++)
            {
                Thread aa = new Thread(new ThreadStart(RunThread));
                aa.Start();
            }
        }
    }
}

 

  • Task, Task<TResult>

- 비동기 코드

- Action delegate

- Func delegate

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace _142_tasks
{
    class Program
    {
        static void TaskMethod()
        {
            Thread.Sleep(500);
            Console.WriteLine("TaskMethod");
        }
        static int TaskMethodParam(object num)
        {
            Thread.Sleep(200);
            Console.WriteLine("TaskMethod num : " + num);
            return (int)num * 10;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Main Thread Start");

            Task aa = new Task(TaskMethod);
            aa.Start();

            Task<int> bb = new Task<int>(TaskMethodParam, 10); //TaskMethodParam(10);
            bb.Start();
            bb.Wait();
            Console.WriteLine("Result : " + bb.Result);

            //aa.Wait(); //대기하지 않으면 비동기 TaskMethod 종료

            Console.WriteLine("Main Thread End");
        }
    }
}

728x90

'게임 프로그래밍 > C#' 카테고리의 다른 글

C# 선형 자료구조 - 배열  (1) 2021.12.25
C# 자료구조 Data Structure  (0) 2021.12.25
C# 파일 처리 Stream, System.IO  (0) 2021.12.23
C# LINQ(Select, Oderby, Group, Join)  (0) 2021.12.21
C# 람다식 Ramdba  (0) 2021.12.21