Question about terminating a thread cleanly in .NET
내가 부딪힌 문제와 비슷하다. worker thread 에서 열심히 작업하고 있는데, 이 worker thread 에는 UI thread 에 접근하는 invoke 가 있다.
그런데 close button 에 의해서 UI Thread 가 Dispose 되는 경우에 worker thread 가 operation 을 계속 진행하다가 invoke 부분에서 ObjectDisposedException 이 발생했다.
참고로,
- 이 worker thread 는 IsBackground 가 true 로 설정되어 있다.
- application 은 debug mode 로 실행되고 있다.
Thread 를 종료하는 방법들
그래서 위의 글에서는 이 문제의 해결책으로 아래와 같은 방법을 제안하고 있다.- try /catch 를 이용해서 처리한다. Thread.Interrupt() 사용해서 ThreadInterruptException 을 발생시킨다.
- flag 변수 사용 : volatile 변수를 이용해서 worker thread 에서 check 를 하는 것.
- TPL(Task Parallel Library) 를 이용하는 방법
- WaitHandles 를 이용하는 방법
catch ObjectDisposedException
근데 내 경우는 Thread 의 operation 을 정확히 마칠 필요가 없다. 그냥 종료하는 시점에 Exception 의 발생이 신경 쓰이는 것 뿐이다.이런 경우는 그냥 Disposed Object 를 접근해서 ObjectDisposedException 을 발생시킨 것이기 때문에 이 Exception 을 catch 해서 종료를 하면 될 듯 하다.
try{…} catch(ObjectDisposedException e) {그런데 이런 식으로 해결을 하려 했으나, ObjectDisposeException 이 아닌 InvalidOperationException 도 발생했다. 그래서 그냥 Exception 을 catch 하는 것으로 처리를 했다.
Console.WriteLine(e.Message);
}
IsDisposed Property
신기한 부분 중에 하나는 ObjectDisposedException 을 catch 한 후에 IsDisposed Property 를 보니 true 이어서 이 IsDisposed 를 이용해서 false 일 때만 object 에 접근하도록 하면 굳이 try/ catch 를 안 써도 될 듯 했는데 테스트를 해보니 IsDisposed 가 false 인 ObjectDisposedException 이 발생했다. 그래서 사용할 수 없었다.좀 더 나은 방법?
ref. 3 에 훨씬 예쁜(graceful) 방법이 나와 있다. 이 방법을 응용하면, Thread 에서 while loop 을 돌 때 flag 를 하나 두고, 이 flag 를 false 로 만드는 Thread.RequestStop() 을 만든다. 그리고 나서 Dipose() 에서 Thread.RequestStop() 을 호출하고, Thread.Join() 을 통해 그 thread 가 종료하기를 기다리는 방법으로 Thread 종료를 할 수 있다.하지만, 이 방법도 Join 을 해서 한없이 Thread 를 기다리게 할 수는 없다. 한없이 기다린다면, UI 가 멈춰있게 될 것이다. 그런데 Worker thread 가 오랜 시간이 걸리는 연산을 수행하고 있다면, 결국 의미없게 된다. 결국 나는 위의 방법을 다시 택해야 했다.
댓글 없음:
댓글 쓰기