멀티스레딩(Main Threading)은 여러 코어에서 한 번에 여러 개의 스레드를 처리하는 CPU 성능을 활용하는 프로그래밍의 한 유형입니다.
한 번에 하나가 아니라, 동시에 여러 개의 작업 또는 명령을 실행합니다.
어떤 스레드는 기본적으로 프로그램이 시작할 때 실행됩니다.
이 스레드가 바로 메인 스레드(Main Thread)입니다.
메인 스레드는 작업을 처리하기 위해 새로운 스레드를 생성합니다.
이러한 새 스레드는 다른 스레드와 병렬로 실행되며, 대개 실행이 완료되면 메인 스레드와 결과를 동기화합니다.
유니티에서 제공하는 많은 메서드들은 메인 스레드에서 실행되어야 합니다.
하지만, C#에서 제공하는 기능이나, 통신, 파일 로딩, 파싱 같은 것들은 멀티 스레드를 사용하면 됩니다.
1. 스레드 시작
네임 스페이스 |
using System.Threading; |
1.1 스레드 생성
Thread 스레드변수명 = new Thread(스레드메서드명);
스레드변수명.Start()
...
스레드메서드
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(Run);
thread.Start();
}
void Run()
{
Debug.LogFormat("Thread#{0}: 시작", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Debug.LogFormat("Thread#{0}: 종료", Thread.CurrentThread.ManagedThreadId);
}
}
Thread.Sleep(int millisecondsTimeout);는 스레드를 milliseconds 만큼 중지시킵니다.
1.2 ThreadStart 델리게이트 사용하여 스레드 생성
Thread 스레드변수명 = new Thread(new ThreadStart(스레드메서드명));
스레드변수명.Start()
...
스레드메서드
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(new ThreadStart(Run));
thread.Start();
}
void Run()
{
Debug.LogFormat("Thread#{0}: 시작", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Debug.LogFormat("Thread#{0}: 종료", Thread.CurrentThread.ManagedThreadId);
}
}
1.3 람다식을 사용하여 스레드 생성
Thread 스레드변수명 = new Thread(() => 스레드메서드명());
스레드변수명.Start()
...
스레드메서드
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(() => Run());
thread.Start();
}
void Run()
{
Debug.LogFormat("Thread#{0}: 시작", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Debug.LogFormat("Thread#{0}: 종료", Thread.CurrentThread.ManagedThreadId);
}
}
1.4 익명메서드를 이용한 스레드 생성
Thread 스레드변수명 = new Thread(delegate ()
{
스레드메서드명();
});
스레드변수명.Start()
...
스레드메서드
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(delegate ()
{
Run();
});
thread.Start();
}
void Run()
{
Debug.LogFormat("Thread#{0}: 시작", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Debug.LogFormat("Thread#{0}: 종료", Thread.CurrentThread.ManagedThreadId);
}
}
1.5 간단한 표현으로 스레드 바로 실행하기
new Thread(() => 스레드메서드명()).Start();
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
new Thread(() => Run()).Start();
}
void Run()
{
Debug.LogFormat("Thread#{0}: 시작", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Debug.LogFormat("Thread#{0}: 종료", Thread.CurrentThread.ManagedThreadId);
}
}
2. 스레드 매개변수 전달
2.1 매개변수가 1개인 경우
매개변수가 1개이면, 스레드 생성 할 때는 매개변수를 넣어 주지 않고, Start 메서드를 사용할 때 넣어 주면 됩니다.
Thread 스레드변수명 = new Thread(스레드메서드명);
스레드변수명.Start(매개변수)
...
스레드메서드(Object obj)
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(Run);
thread.Start(1);
}
static void Run(object obj)
{
Debug.Log(obj);
}
}
2.2 매개변수가 2개 이상인 경우
매개변수가 2개 이상이면, ThreadStart에서 파라미터 전달하면 됩니다.
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(() => Sum(1, 2, 3));
thread.Start();
}
static void Sum(int d1, int d2, int d3)
{
int sum = d1 + d2 + d3;
Debug.Log(sum);
}
}
3. 백그라운드 스레드
일반적으로 스레드는 포그라운드(Foreground)에서 실행됩니다.
만약, 스레드를 백그라운드(Background)로 실행하고 싶으면, Start()를 실행하기 전에 IsBackground 속성을 true로 지정하면 됩니다.
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(new ThreadStart(Run));
thread.IsBackground = true;
thread.Start();
}
static void Run()
{
Debug.Log("Run");
}
}
4. 스레드 대기
4.1 Join 메서드
메인 스레드에서 서브 스레드를 실행시키고, 서브 스레드가 실행되는 동안 메인 스레드를 블락시켜 스레드를 대기 시키는 방법으로 Join 메서드를 사용합니다.
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(Run);
thread.Start();
for (int i = 0; i < 3; i++)
{
Debug.LogFormat($"메인 스레드 : {i}");
Thread.Sleep(100);
}
thread.Join();
Debug.Log("메인 스레드 종료");
}
static void Run()
{
for (int i = 0; i < 5; i++)
{
Debug.LogFormat($"서브 스레드 : {i}");
Thread.Sleep(100);
}
Debug.Log("서브 스레드 종료");
}
}
4.2 EventWaitHandle 클래스 사용
EventWaitHandle 클래스의 WaitOne 메서드와 Set 메서드를 사용하여스레드를 블락시킵니다.
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
EventWaitHandle eventWaitHandle
= new EventWaitHandle(false, EventResetMode.ManualReset);
Thread thread = new Thread(Run);
thread.Start(eventWaitHandle);
Debug.Log("서브 스레드 시작");
for (int i = 0; i < 1; i++)
{
Debug.LogFormat($"메인 스레드 : {i}");
Thread.Sleep(100);
}
eventWaitHandle.WaitOne();
Debug.Log("메인 스레드 종료");
}
static void Run(object obj)
{
EventWaitHandle eventWaitHandle = obj as EventWaitHandle;
for (int i = 0; i < 2; i++)
{
Debug.LogFormat($"서브 스레드 : {i}");
Thread.Sleep(100);
}
Debug.Log("서브 스레드 종료");
eventWaitHandle.Set();
}
}
5. 스레드 폴링
스레드 메서드는 하나를 만든 뒤, 재사용이 가능한데 이를 스레드 폴링이라 합니다.
스레드 폴링은 ThreadPool클래스의 QueueUserWorkItem메서드를 사용하면 됩니다.
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
ThreadPool.QueueUserWorkItem(Run); // 출력 : null
ThreadPool.QueueUserWorkItem(Run, 1); // 출력 : 1
ThreadPool.QueueUserWorkItem(Run, 2); // 출력 : 2
}
static void Run(object obj)
{
Debug.Log(obj);
}
}
6. 스레드 강제 종료
서버 스레드가 실행 중에 메인 스레드에서 강제로 종료하고 싶으면, Abort 메서드를 사용하면 됩니다.
using UnityEngine;
using System.Threading;
public class ThreadDemo : MonoBehaviour
{
void Start()
{
Thread thread = new Thread(Run);
thread.Start();
for (int i = 0; i < 3; i++)
{
Debug.LogFormat($"메인 스레드 : {i}");
Thread.Sleep(100);
}
thread.Abort();
Debug.Log("메인 스레드 종료");
}
static void Run()
{
for (int i = 0; i < 5; i++)
{
Debug.LogFormat($"서브 스레드 : {i}");
Thread.Sleep(100);
}
}
}
'프로그램 > 유니티 C# 강좌' 카테고리의 다른 글
[유니티 C# 강좌] 24. 파일 입출력 (0) | 2021.06.22 |
---|---|
[유니티 C# 강좌] 22. 링크(LINQ, Language-Integrated Query) (1) | 2020.02.11 |
[유니티 C# 강좌] 21. 제네릭 컬렉션(General Collection) (1) | 2020.02.09 |
[유니티 C# 강좌] 20. 병렬 프로그래밍 (Parallel Programming) (0) | 2020.02.09 |
[유니티 C# 강좌] 19. 비동기 프로그래밍(Asynchronous Programming) (0) | 2020.02.06 |