[컴][C#] windows forms application 에서 close button 으로 UI thread 가 종료된 후에 worker thread 를 잘 종료하는 방법

windows forms application 에서 close button 으로 UI thread 가 종료된 후에 worker thread 를 잘 종료하는 방법
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 를 종료하는 방법들

그래서 위의 글에서는 이 문제의 해결책으로 아래와 같은 방법을 제안하고 있다.
  1. try /catch 를 이용해서 처리한다.  Thread.Interrupt() 사용해서 ThreadInterruptException 을 발생시킨다.
  2. flag 변수 사용 : volatile 변수를 이용해서 worker thread 에서 check 를 하는 것.
  3. TPL(Task Parallel Library) 를 이용하는 방법
  4. WaitHandles 를 이용하는 방법

catch ObjectDisposedException

근데 내 경우는 Thread 의 operation 을 정확히 마칠 필요가 없다. 그냥 종료하는 시점에 Exception 의 발생이 신경 쓰이는 것 뿐이다.
이런 경우는 그냥 Disposed Object 를 접근해서 ObjectDisposedException 을 발생시킨 것이기 때문에 이 Exception 을 catch 해서 종료를 하면 될 듯 하다.
try{…} catch(ObjectDisposedException e) {
                Console.WriteLine(e.Message);
            }
그런데 이런 식으로 해결을 하려 했으나, ObjectDisposeException 이 아닌 InvalidOperationException 도 발생했다. 그래서 그냥 Exception 을 catch 하는 것으로 처리를 했다.

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 가 오랜 시간이 걸리는 연산을 수행하고 있다면, 결국 의미없게 된다. 결국 나는 위의 방법을 다시 택해야 했다.


References

  1. http://stackoverflow.com/questions/3944872/how-do-i-properly-close-a-c-sharp-application-that-has-created-multiple-threads
  2. http://stackoverflow.com/questions/3641147/object-disposed-exception-and-multi-thread-application
  3. 방법: 스레드 만들기 및 종료(C# 프로그래밍 가이드), msdn

댓글 없음:

댓글 쓰기