흔한 덕후의 잡동사니
C#의 스레드에 관하여 본문
.NET Framework 4부터 다중 스레딩을 사용하는 권장 방법은 TPL(작업 병렬 라이브러리) 및 PLINQ(병렬 LINQ)를 사용하는 것이다.
TPL 및 PLINQ는 ThreadPool 스레드를 사용하는데, ThreadPool은 C++의 IOCP 방식으로 관리된다. 스레드 풀의 최대 스레드 갯수는 Task 등 내부적으로 비동기 방식을 사용하는 모든 기능에 영향을 미치므로 하드웨어에 비해 성능이 나오지 않는다면 스레드 갯수를 바꿔가며 테스트해보자.
물론 개별적으로 스레드를 만들어 등록할 수 도 있지만 C#에서는 스레드풀과 관련된 여러 API들이 많아 코드의 이해도 상향과 프로젝트의 관리를 위해 System.Threading에서 제공하는 API를 사용하는 것이 좋다.
C#의 스레드는 한가지 특이한 점이 있는데, [ 백그라운드/포그라운드 ] 스레드이다. 기본적으로 스레드를 생성하면 포그라운드 스레드 속성으로 생성되는데, IsBackground 변수를 true로 바꿔줌으로서 백그라운드 스레드로 변경할 수 있다.
백그라운드 스레드의 경우 모든 포그라운드 스레드가 종료되면 강제로 중단되는 성질을 가지고 있다. 이는 중단시 데이터 유실이 있어도 상관없고, 미완성 작업이어도 괜찮은 작업들을 분배해 프로세스 종료시 신경쓰지 않아도 의도적으로 종료시킨다는 의미로 사용된다.
C++의 경우 main 스레드가 종료되어 프로세스의 종료를 명시하더라도 실행과정에서 생성된 다른 스레드들이 돌아가고 있다면 언젠가 강제종료되겠지만 내부적으로 생성한 지역 객체의 메모리 해제등 안전한 종료를 할 수 없어 기록하고 있던 로그가 있을 시 오염이 생길 수 있다. 물론 백그라운드 스레드를 사용하더라도 강제종료되며 안전하지 않은 종료를 하는 것은 마찬가지이다. 어짜피 종료될건데 강제종료하는게 무슨 상관이냐? C++에서 파일 입출력은 해당 함수를 호출할 때 기록되는 것이 아닌 명시적으로 파일 핸들을 닫을 때 기록되는 것이 보장된다. 외부에서 강제로 종료되는 것은 기록하는 함수를 호출했다 하더라도 실제로 기록하지 않았을 위험이 있는 것이다.
그렇다면 백그라운드 스레드는 왜 사용하는가? 보통 " 애플리케이션 종료를 지연시키지 않으면서 부가적인 작업을 처리할 때" 사용하는데, 로그를 찍을 때 많이 사용한다. 이 로그는 정말 중요한 에러가 같은게 아닌 TPS, 메모리 풀 사용량 등 게임의 전반적인 상황을 볼 때 사용하면 좋다.
'언어 관련 > C#' 카테고리의 다른 글
C++ 템플릿과 C# 제네릭의 차이점 (0) | 2025.02.11 |
---|---|
C# 파일 입출력에 대하여 (0) | 2025.02.04 |
new 키워드, 그리고 boxing/unboxing에 대하여 (0) | 2025.01.31 |
List<T>와 LinkedList<T> 의 차이점(ps. 트리 구조) (0) | 2025.01.27 |