Multi Thread 환경에서 UpdateWindow
전에 어느 블로그에선가
Thread에서 UpdateWindow함수를 호출해서는 안된다는 글을 본 적이 있었다.
그러나 그 당시에는 그냥 무심코 넘겼던 말이
오늘에서야 절감하게 되었다.
이 글 또한 누군가가 보게 되면서 크게 3가지 반응을 보일 것으로 생각된다.
1. 쓰레드가 뭐야? -_-a 나랑 전혀 관련이 없는 말이군..
2. 저걸 이제야 알다니. 쯔쯧
3. 난 아무 문제 없던데.
1, 2번이야 어쩔 수 없지만,
3번의 반응을 보인 사람은 언제가 이 글을 기억하게 될 것이다. (뼈저리게..)
흔히 멀티 쓰레드의 가장 큰 문제는 공유자원을 어떻게 동기화해서 접근하느냐
일 것이다.
상황을 만들어 본다면..
만약 Critical Section으로 메인 쓰레드를 Lock을 걸고, 다른 쓰레드가 공유자원에 접근해서 이런 저런 처리를 한다.
그리고 그 처리한 결과를 실시간으로 보여주기 위해 메인 쓰레드가 가지고 있는
Dialog에서 UpdateWindow를 실행한다.
그러나 이때 UpdateWindow 내부적으로 WM_PAINT를 SendMessage하는데
(Invalidate를 호출해도 마찬가지이다.)
알다시피 SendMesssage는 메세지의 처리를 기다리는 속성을 가지고 있는데
WM_PAINT를 처리하는 메인쓰레드는 이미 Lock이 걸려있기 때문에
DeadLock이 발생하여 프로그램은 뻗어버린다.
중요한 것은 UpdateWindow 만 그런 것이 아니라,
SendMessage가 내부적으로 이루어지는 모든 것들이 그럴 수 있다는 것이다.
가령 Progress Bar의 상태를 갱신하기 위해서
SetPos 함수를 호출한다거나 Static Control에 SetWindowText를 호출한다거나 하는 등등 과정도 DeadLock에 빠뜨릴 위험이 있다.
그렇다면 어떻게 해야 할 것인가?
방법은 무수하게 많다.
가장 쉬우면서 확실한 것은 쓰레드가 UI를 표현하는 경우 반드시 그 자체를 쓰레드로 만들면 될 것이다.
또한 메인쓰레드가 Lock이 걸리지 않게 보장해 주면 될 것이고..
답은 무수히 많으나.
경계해야 점을 한가지 짚어본다면..
일단 흔히 멀티 쓰레드를 생각하지 않고 거의 완성을 하다시피 프로그래밍을 한 다음 테스트 과정에서 인터렉티브한 반응이 나오지 않아 멀티 쓰레드 환경으로
급히 수정하는 경우가 종종 있는데.
이때는 엄청나게 위험한 사항등이 많이 존재할 수 있다.
그 위험 사항들을 발견하고 뒤늦게 버그들을 수정하는 시간이 이미 개발한 시간보다 더 들 수도 있을 것이다.
결론적으로 멀티쓰레딩 프로그래밍을 할 때는 초반 설계를 완벽히 하지 않으면 안된다는 것이고, 피치못하게 멀트쓰레드로 선회할 때는 위험사항을 감수하고 기본 설계부터 다시한번 살펴보는 것이 필요할 것이다.
Thread에서 UpdateWindow함수를 호출해서는 안된다는 글을 본 적이 있었다.
그러나 그 당시에는 그냥 무심코 넘겼던 말이
오늘에서야 절감하게 되었다.
이 글 또한 누군가가 보게 되면서 크게 3가지 반응을 보일 것으로 생각된다.
1. 쓰레드가 뭐야? -_-a 나랑 전혀 관련이 없는 말이군..
2. 저걸 이제야 알다니. 쯔쯧
3. 난 아무 문제 없던데.
1, 2번이야 어쩔 수 없지만,
3번의 반응을 보인 사람은 언제가 이 글을 기억하게 될 것이다. (뼈저리게..)
흔히 멀티 쓰레드의 가장 큰 문제는 공유자원을 어떻게 동기화해서 접근하느냐
일 것이다.
상황을 만들어 본다면..
만약 Critical Section으로 메인 쓰레드를 Lock을 걸고, 다른 쓰레드가 공유자원에 접근해서 이런 저런 처리를 한다.
그리고 그 처리한 결과를 실시간으로 보여주기 위해 메인 쓰레드가 가지고 있는
Dialog에서 UpdateWindow를 실행한다.
그러나 이때 UpdateWindow 내부적으로 WM_PAINT를 SendMessage하는데
(Invalidate를 호출해도 마찬가지이다.)
알다시피 SendMesssage는 메세지의 처리를 기다리는 속성을 가지고 있는데
WM_PAINT를 처리하는 메인쓰레드는 이미 Lock이 걸려있기 때문에
DeadLock이 발생하여 프로그램은 뻗어버린다.
중요한 것은 UpdateWindow 만 그런 것이 아니라,
SendMessage가 내부적으로 이루어지는 모든 것들이 그럴 수 있다는 것이다.
가령 Progress Bar의 상태를 갱신하기 위해서
SetPos 함수를 호출한다거나 Static Control에 SetWindowText를 호출한다거나 하는 등등 과정도 DeadLock에 빠뜨릴 위험이 있다.
그렇다면 어떻게 해야 할 것인가?
방법은 무수하게 많다.
가장 쉬우면서 확실한 것은 쓰레드가 UI를 표현하는 경우 반드시 그 자체를 쓰레드로 만들면 될 것이다.
또한 메인쓰레드가 Lock이 걸리지 않게 보장해 주면 될 것이고..
답은 무수히 많으나.
경계해야 점을 한가지 짚어본다면..
일단 흔히 멀티 쓰레드를 생각하지 않고 거의 완성을 하다시피 프로그래밍을 한 다음 테스트 과정에서 인터렉티브한 반응이 나오지 않아 멀티 쓰레드 환경으로
급히 수정하는 경우가 종종 있는데.
이때는 엄청나게 위험한 사항등이 많이 존재할 수 있다.
그 위험 사항들을 발견하고 뒤늦게 버그들을 수정하는 시간이 이미 개발한 시간보다 더 들 수도 있을 것이다.
결론적으로 멀티쓰레딩 프로그래밍을 할 때는 초반 설계를 완벽히 하지 않으면 안된다는 것이고, 피치못하게 멀트쓰레드로 선회할 때는 위험사항을 감수하고 기본 설계부터 다시한번 살펴보는 것이 필요할 것이다.
"프로그래밍 / TIP& Study" 분류의 다른 글
| [퀴즈] SQLite collate 문제 (0) | 2010/07/16 |
| [TIP] XP, Vista에서 CD/DVD롬이 보이지 않을 경우 (1) | 2009/08/05 |
| [C#] WinForm 에서 Docking 순서 변경하기 (0) | 2009/07/29 |
| [WPF] InkCanvas 사용하기 (0) | 2009/06/29 |
| [C#] Control Library 만들 때 TIP (0) | 2009/06/26 |
| [C#] 자연스럽게 Pen으로 그리기 (0) | 2009/06/23 |
| [WPF] Canvas의 Width, Height Binding (0) | 2009/06/23 |
| [C#] DateTime으로 7일 후는 어떻게? (0) | 2009/06/23 |
프로그래밍/TIP& Study
2006/06/28 01:29

댓글을 달아 주세요