본문 바로가기

프로그래밍

WPF UI 사용법(너무 느린 WPF 프로그램 개선방안)





WPF로 프로그래밍하다보면 너무 느려서(저사양 PC에서 주로 발견) 못쓰겠다는 사태가 나타났습니다.

 

이리저리 찾아보다가 필요한 사항을 정리해 보았습니다.

 

1. UI 스레드

다른 스레드에서 UI 요소(Textbox, Lable 등)의 정보를 갱신하려면 아래와 같은 오류가 발생합니다.

다른 스레드가 이 개체를 소유하고 있어 호출한 스레드가 해당 개체에 액세스할 수 없습니다.

이 상황에서 많이 사용하는 방식이 Dispatcher.Invoke 입니다.

 

간단한게 사용하기 쉬워서 자주 쓰다보면 프로그램이 느려지거나 어느 순간 먹통이 되는 사태가 발생합니다.

 

 

MSDN에서는 이렇게 설명합니다.

Dispatcher.Invoke 는 동기로 실행되기 때문에 요청을 처리할 때까지 다른 동작이 차단됩니다.
대신 Dispatcher.BeginInvoke 를 사용하세요.

Dispatcher.BeginInvoke 를 사용하면 나아지긴 하지만 중복된 실행을 발생하게되서 프로그램이 느려지거나 어느 순간 먹통이 되는 사태가 발생합니다.

 

그래서 어떤 개발자는 UI 스레드에서 모든 걸 해결하는게 좋다고 아래와 같이 얘기합니다.

Worker 스레드와 UI 스레드에 관련된 연결을 끊습니다.

그리고 UI 스레드에서 UI 요소를 갱신하게 구현합니다.

그러기 위해서는 Timer를 사용해서 UI를 주기적으로 갱신해줍니다.

 

직접적인 접근 방법이 아니라 타이머에 의존한다는 것이 조금 걸리긴 하지만 이런 방식이 프로그램이 느려지는 것을 방지할 수 있다고 합니다.

 

WPF에서 UI 업데이트를 지원하는 System.Windows.Threading.DispatcherTimer 는 입니다.

 

예제는 다음과 같습니다.

DispatcherTimer timer = new DispatcherTimer();
timer.IsEnabled = true;
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += Timer_Tick;
timer.Start();

 

2. Parallel.ForEach(병렬 처리)

빠른 수행을 위해 병렬로 처리하는 경우가 있지만, 장애가 올 수 있다는 사실을 유의해야합니다.

 

단순히 병렬로 동시에 처리하기 때문에 빠르게 처리할 수 있다고 생각하지만

 

갑자기 CPU 점유율 많이 차지해서 운영체제에 많은 부담을 주기 때문에 전반적인 윈도우 사용에 문제가 될 소지가 있습니다.

 

그리고 일부 환경에서는 그다지 빠르지 않고 오히려 성능이 악화되는 요인이 되기도 합니다.

 

 

 

참고 : https://stackoverflow.com/questions/10211096/thread-runs-slow-when-invoke-ui-element