C# Thread가 Running 상태인지 아는 방법
Thread가 실행 상태인지 어떻게 알 수 있을까요? 가령 Thread.IsAlive가 왠지 그럴 것 같습니다. 테스트를 해볼까요?
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(threadFunc);
t.Start();
bool alive = t.IsAlive;
Console.WriteLine(alive);
}
private static void threadFunc(object obj)
{
Console.WriteLine("TEST: " + obj);
}
}
위의 코드에서 Console.WriteLine에 BP를 걸고 비주얼 스튜디오를 시작한 후 Ctrl+Alt+H 단축키를 눌러 Threads 창을 띄우면 결과를 알 수 있습니다. t.IsAlive는 true이지만 t 스레드는 생성조차 되지 않은 것을 볼 수 있습니다. 즉 t.IsAlive는 Thread 객체가 생성된 후 Start 메서드가 불린 순간부터 무조건 true이고 그 이후 스레드 종료가 되어야 false로 바뀌는 것입니다.
다음 후보로 Thread.ThreadState는 어떨까요? ThreadState enum 값에는 분명히 Running이 있으니 다음과 같이 테스트할 수 있습니다.
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(threadFunc);
t.Start();
bool alive = t.IsAlive;
bool running = t.ThreadState == ThreadState.Running;
Console.WriteLine(alive);
}
private static void threadFunc(object obj)
{
Console.WriteLine("TEST: " + obj);
}
}
그런데 이것 역시 BP를 걸어 테스트해보면 실제 스레드 생성 유무와 상관없이 Thread.Start 이후 Running 상태임을 알 수 있습니다. 설령 이 필드가 그 의미 그대로 Running이라고 해도 문제입니다. 왜냐하면 필드의 값이 0이기 때문입니다.
[ComVisible(true)]
[Flags]
public enum ThreadState
{
Running = 0,
StopRequested = 1,
SuspendRequested = 2,
Background = 4,
Unstarted = 8,
Stopped = 16,
WaitSleepJoin = 32,
Suspended = 64,
AbortRequested = 128,
Aborted = 256
}
따라서 Thread.IsBackground = true; 같은 식으로 설정해 버리면 Running을 알아낼 방법이 없습니다. 왜냐하면 다음의 조건도 false이고,
bool running = t.ThreadState == ThreadState.Running; // ThreadState == 4 (Background)이므로.
그렇다고 다음과 같이 해도 Running이 0이므로 항상/무조건 true가 나옵니다.
bool running = (t.ThreadState & ThreadState.Running) == ThreadState.Running;
결국 가장 적당한 방법은 스레드 함수가 실행하는 초기/후기에 EventWaitHandle 등을 이용해 그 사실을 알려주는 것입니다.
static void Main(string[] args)
{
EventWaitHandle started = new EventWaitHandle(false, EventResetMode.ManualReset);
EventWaitHandle exited = new EventWaitHandle(false, EventResetMode.ManualReset);
Thread t = new Thread(threadFunc);
t.Start((started, exited));
bool threadStarted = started.WaitOne(0);
bool threadExited = exited.WaitOne(0);
}
private static void threadFunc(object obj)
{
var events = (System.ValueTuple<EventWaitHandle, EventWaitHandle>)obj;
{
events.Item1.Set();
Console.WriteLine("TEST: " + obj);
events.Item2.Set();
}
}
또는 DONT_USE_InternalThread 등의 내부 필드를 이용해,
.NET System.Threading.Thread 개체에서 Native Thread Id를 구할 수 있을까?
; https://www.sysnet.pe.kr/2/0/1244
그에 상응하는 스레드를 Process.GetCurrentProcess().Threads에서 찾는 방식을 비공식적으로 고려할 수 있습니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]