본문 바로가기

Development/WPF

Improving WPF Application startup time using Winform Splash Screen

Intorduction

WPF Application을 개발하다보면 시간이 흐를 수록 프로그램 규모가 점점 커지면서 프로그램 구동시간이 점점 느려지는 현상이 있습니다. 구동시간이 느린 원인으로는 크게 2가지가 있는데 ,

첫번째는 짐작하고 있듯이 MainWindow를 띄우기 전에 프로그램에서 필요한 여러가지 정보를 로드하기 위한 과정때문에고,
두번째는 WPF가 시스템에서 사용하기 위해 준비하는 과정이 느린 경우입니다.

로드할 데이터가 많다면 Splash Screen을 띄워놓고, 데이터를 비동기로 로드하는 방식을 통해 사용자로 하여금 기다릴 수 있는 UX를 제공해 줄 수 있지만, 여전히 WPF가 준비되는데까지 걸리는 시간을 해결하지는 못합니다. 그래서 이번시간에는 WPF에 비해 준비과정이 필요없는 Winform을 통해 가벼운 SplashScreen을 구성하는 방법에 대해 소개합니다.
(.NET 3.5에서 추가된 SplashScreen BuildAction의 경우 내부적으로 WPF기술을 사용하기 때문에 이 글에서는 제외되었습니다.)



코드를 살펴보면 총 3가지 특징이 있고, 각 부분별로 설명하면 다음과 같습니다.

WPF Application에서의 Main함수 

WPF Application에서는 기본적으로 App Class에 Main함수가 자동으로 구현되어 따로 Main함수를 만들어 줄 필요가 없습니다. Application 시작과 관련된 대부분의 코드는 App의 StartUp메서드를 Override하여 처리 할 수 있지만 App이 생성되면서 로드하게 되는 수많은 Assembly 로드과정을 SplashScreen이 출력된 이후로 미루고자 별도의 Main함수를 구현하여 사용했습니다. (추가로 구현한 Main함수는 프로젝트 설정에서 따로 선택할 수 있습니다.)

SplashImage를 가져오기 위한 GetManifestResourceStream

WPF에서는 Build Actino이 Resource인 데이터를 가져오기 위해 Application.GetResourceStream과 같은 메서드를 제공하고 있습니다. 이 메서드를 사용해도 결과적으로는 동일하지만 Application.GetResourceStream를 사용해 내부적으로 로드되는 어셈블리를 미루고자Assembly에서 데이터를 바로 꺼내올 수 있는 GetManifestResourceStream를 사용했습니다. (해당 리소스를 Embedded Resource로 설정해야 합니다.)

CompositionTarget.Rendering

WPF의 경우 기본적으로 전용 Renderer에 의해 화면이 Rendering 되기 때문에 DC에 직접 그리는 Winform과 달리 화면에 출력되는 시점을 정확하게 알 수가 없습니다. 다만 프로그램이 안정적으로 렌더링 되고 있다는 것을 확인 할 수 있는데, WPF 화면을 렌더링 하기전에 호출되는 CompositionTarget.Rendering 이벤트를 이용합니다.

WPF는 기본적으로 시스템에서 안정적으로 동작할 수 있는 FPS를 유지하게 되는데, 최소 30~60FPS를 유지 합니다. 그래서 Rendering 이벤트에 30FPS이상의 속도로 렌더링이 되고 있는 시점을 로드가 모두 완료되었다고 판단하고 SpalshScreen을 종료합니다.

첨부된 파일은 이번시간에 사용된 전체 소스코드이며 기타 궁금하신 점이나 문의사항은 이메일이나 댓글로 남겨주시면 답변드리겠습니다.

WIT.WPF.SplashScreenExample.zip