5강 쓰레드 생성
ServerCore 파일의 Program.cs (중요) 에서
다음 코딩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using System.Threading;
namespace ServerCore
{
class Program
{
static void MainThread()
{
Console.WriteLine("Hello Thread!");
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread); //MainThread 스레드 생성 (서브 직원)
t.Start(); //일을 하라고 명령. (스레드 실행)
Console.WriteLine("Hello Main!");
}
}
}
C#의 스레드는 기본적으로 앞에서 실행되게 만들어진다 (폴 그라운드) ↔ 백그라운드
1
t.IsBackground = true;
백그라운드 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void MainThread()
{
while(true)
Console.WriteLine("Hello Thread!");
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread); //MainThread 스레드 생성 (서브 직원)
t.IsBackground = true;
t.Start(); //일을 하라고 명령. (스레드 실행)
Console.WriteLine("Hello Main!");
}
- 다음과 같다면 백그라운드 실행 스레드는 폴그라운드 실행 스레드가 끝나면 자동 종료됨
백그라운드 실행 종료 대기하기
1
2
Console.WriteLine("Waiting for Thread!");
t.Join();
스레드 이름 설정
1
t.Name = "Test Background Thread";
다음과 같이 확인 가능
)
스레드풀링 (단기알바 고용)
1
2
3
4
5
6
7
8
9
10
11
12
13
static void MainThread(object state)
{
for(int i=0; i<5; i++)
Console.WriteLine("Hello Thread!");
}
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(MainThread);//단기알바 모집
//백그라운드로 돌아가는 스레드
while (true) { }
}
- 결과: 스레드 업무를 다 실행한 다음 종료되지 않고 지속
원리
이미 스레드들이 마련되어있음 (직원 고용이 완료) ⇒ 스레드 대기소에서 대기중인 상태
스레드의 할일 실행 ⇒ 스레드의 할일이 끝나면, 다시 스레드 대기소 들어가서 대기함
주의 점
기존에 있던 풀에서 활용을 하는 것이므로, 풀에 비해서 일감이 많을 시
먹통이 될 수가 있다 (예- 무한루프 일감)
= 기존 인력이 돌아오지 않는 경우
cf) 오브젝트 풀링
오브젝트를 풀에 대기시켰다가 필요할때가 되면 재사용함
이와 같은 원리임
스레드가 너~무 많을 시
1
2
3
4
5
6
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(MainThread); //MainThread 스레드 생성 (서브 직원)
//t.Name = "Test Background Thread";
t.IsBackground = true;
t.Start(); //일을 하라고 명령. (스레드 실행)
}
- 1000개의 스레드를 만들어서 일을 시키는 중
어떨까?
스레드를 생성해서 일을 시키는 일이
스레드가 실제로 해야 할 일을 하는 것보다 오랜 시간이 걸릴 것 ⇒ 🤮최악!
영영 돌아오지 않는 스레드
일감 (hello thread 5번 출력)
1
2
3
4
5
static void MainThread(object state)
{
for(int i=0; i<5; i++)
Console.WriteLine("Hello Thread!");
}
스레드 인력 사무소
1
2
3
4
5
6
7
8
9
10
11
12
static void Main(string[] args)
{
ThreadPool.SetMinThreads(1, 1); //최소 스레드 1개
ThreadPool.SetMaxThreads(5, 5); //최대 스레그 5개 설정
for (int i = 0; i < 5; i++) {
//obj를 받아서 무한루프를 실행하도록 해줌
ThreadPool.QueueUserWorkItem((obj)=> { while (true) { } });
}
ThreadPool.QueueUserWorkItem(MainThread);//단기알바 모집
//일감 (hello thread 5번 출력)
}
해석
1
2
3
4
for (int i = 0; i < 5; i++) {
//obj를 받아서 무한루프를 실행하도록 해줌
ThreadPool.QueueUserWorkItem((obj)=> { while (true) { } });
}
스레드가 5개가 존재함.
이 부분에서 5개의 스레드가 무한 루프를 돌고있어 남는 스레드가 없으므로 일감을 수행할 스레드가 없어서 먹통이 된다
Task ⇒ 스레드의 먹통 단점 극복
결과: 먹통이 되는 일감이 있어도, MainThread 일들을 일단 처리하게 될 것
1
2
3
4
Task t = new Task(() => { while (true) { } }, TaskCreationOptions.LongRunning);
//오래 걸리는 작업임을 알려줌
t.Start();
Task
직원이 할 일감 단위를 정해줌
스레드 풀에 넣어져서 관리하게 활용할 것
옵션 설명
🔥
TaskCreationOptions.LongRunning
: 오래 걸리는 일감임을 알려줌
- 이 기능으로 먹통이 될 일이 없게 된다 (이 옵션이 없다면 다시 먹통이 됨)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void MainThread(object state)
{
for(int i=0; i<5; i++)
Console.WriteLine("Hello Thread!");
}
static void Main(string[] args)
{
ThreadPool.SetMinThreads(1, 1);
ThreadPool.SetMaxThreads(5, 5);
for (int i = 0; i < 5; i++) {
//오래 걸리는 작업임을 알려줌
Task t = new Task(() => { while (true) { } }, TaskCreationOptions.LongRunning);
t.Start();
}
}
* 람다 식*
같은 의미이다
1
2
3
4
5
6
7
8
9
static void MainThread(object state)
{
while(true) {}
}
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(MainThread);//단기알바 모집
}
object
형식으로 state
를 인자로 받는 것
== (obj)=> { while (true) { } }
1
2
3
static void Main(string[] args){
ThreadPool.QueueUserWorkItem((obj)=> { while (true) { } });
}
인자가 없는 람다 식
() => { while (true) { } })