.NET에는 SynchronizationContext가 있다는 것을 다들 아실 거 같습니다.
Console Application은 SynchronizationContext가 null이라서 await 이후 Thread ID가 변경된 상태로 이후의 코드들이 쭉 진행되고,
Windows Forms, WPF, ASP.NET은 각자 SynchronizationContext 구현체가 기본적으로 존재하기 때문에 await 이후로 원래 Thread로 실행 Context가 복귀되기 때문에 Thread ID가 변경되지 않는 현상을 볼 수 있습니다.
여담으로, 저는 웹을 하지 않아서 몰랐는데 ASP.NET Core
의 경우에도 Console Application 때처럼 SynchronizationContext가 없다는 소식을 접하게 되어, 검색해봤더니 진짜로 없는 거 같습니다.
아무튼 각 .NET의 각 프로젝트마다 구현이 다른 것이 문제라면 문제일 수 있겠으나, 이 글에서 궁금한 것은 아래와 같은데요.
SynchronizationContext가 null인 어떤 .NET 프로세스의 환경에 대해서 TAP방식을 이용하여 Worker Thread를 Thread Pool에서 가져다 썼을 경우, 다시 await를 호출하여 다른 Thread로 변경하지 않는다면 Thread Pool의 Thread를 계속 점유하는 것인가?
입니다.
Thread Pool은 제가 알기로는 기본적으로 .NET Process가 시작될 때 4개를 갖고 시작하는 것으로 알고 있으며 장시간 Thread Pool에서 Thread를 가져다가 사용하지 않을 경우 Thread Pool의 Thread도 1개까지 내려가는 것으로 알고 있습니다.
상황을 가정하겠습니다. 상황이 맞는지 검토해주시면 감사하겠습니다.
Main Thread - M Thread
Thread Pool Thread - A, B, C, D Thread
- MainThread를 Entry Point로 진입.
- M Thread 1개 사용
- A,B,C,D Thread 대기
- await 를 1번 사용
- M Thread 1개 노는 중
- B,C,D Thread 대기 중
- A Thread 사용 중
- MainThread 놀고 있음???
- await Task.WhenAll 로 작업시간이 충분히 긴 Task 4개 호출. D Thread가 가장 마지막으로 끝난다고 가정.
- M Thread 1개 노는 중
- B,C,D Thread 사용 중
- E Thread가 Thread Pool에서 새로 생성되어 사용 중
- Thread ID를 확인할 시점에 Context가 가장 마지막에 끝나는 D Thread일 것이므로 A Thread는 노는 중
- 현재 상태
- M Thread 노는 중
- A Thread 대기하다가 Thread Pool로 반환
- B,C,E는 대기하다가 Thread Pool로 반환
- 현재 D Thread에서 코드 실행 중
이 가정이 맞을까요? 그러면 SynchronizationContext가 없는 경우에는 TAP를 한번이라도 한다면 Main Thread는 계속 놀게 되는 것일까요?