Async/Await를 사용해서 UI Freeze 해결하기 (tistory.com)
UI Freeze은 화면이 사용자의 입력에 반응하지 않고, 멈추는 현상을 이야기 합니다. 옛날에는 이 문제를 해결하기 위한 여러가지 꼼수를 사용해야 했지만, 이제는 async/await를 이용하면 쉽게 해결할 수 있습니다.
다들 알고 계신가요? 흐흐흐
우선 이 현상이 발생되는 예제를 만들어 보도록 하겠습니다.
1. MainWindow.xaml (UI Freeze 발생)
CategoryComboBox1, CategoryListBox1, CategoryComboBox2, CategoryListBox2 이렇게 4개의 컨트롤을 배치하고, 각 컨트롤의 SelectixxonChanged 이벤트를 연결했습니다.
콤보박스나, 리스트박스의 SelectixxonChanged 이벤트가 발생되면, GetDatas 메소드를 호출해서 데이터를 조회합니다.
물론 진짜 데이터를 조회하는 것은 아니지만요~
조회된 데이터를 ItemsSource에 넣어고, SelectedIndex에 0을 넣어서 첫번째 아이템이 선택되도록 합니다. 이렇게하면, 다른 컨트롤의 SelectixxonChanged 이벤트가 다시 발생하여 연쇄반응을 일으키게 됩니다.
SelectixxonChanged이벤트는 ItemsSource가 변경될 때와 SelectedItem이 변경될 때 발생합니다. 그래서, Control의 SelectedItem이 null인지 확인하는 코드를 추가했습니다.
GetDatas메소드는 Task.Delay()를 이용해서 강제 지연을 발생 시킵니다. 반환되는 데이터는 selectedString과 연결되어있습니다.
실행하면 어떻게 될까요?
따란~ 15초간 아무것도 보이지도, 사용자 입력도 불가능한 상태를 지속하다가...
한번에 모든 데이터가 표시됩니다. 여기서, 콤보박스나 리스트박스의 아이템을 하나 변경하면, 또 다시 UI Freeze가 발생하고, 시간이 지나면 화면이 갑자기 갱신됩니다.
옛날 옛날에는 이렇게 되는 것을 막아 볼려고 별짓을 다 했었는데... 물론 지금도 괴로워하는 개발자가... 있겠죠?
2. SecondWindow.xaml (async/await 버전)
애플리케이션 실행을 SecondWindow.xaml로 변경하기 위해서는 App.xaml.cs에 StartupUri를 수정합니다.
GetDatasAsync 메소드에서는 await Task.Delay(sleep);를 이용해서 강제로 대기시간을 발생시키고 있습니다.
나머지는 위에서 사용한 GetDatas 메소드와 동일합니다.
HttpClient나 서비스 등의 호출 후 대기하는 부분을 async/await로 만들어서 활용하시면 됩니다.
SelectixxonChanged 이벤트가 발생할 때마다, GetDatasAsync 메소드를 await 키워드를 추가해서 호출해주기만 하면됩니다. 참 쉽죠?
실행을 해보겠습니다.
첫 실행화면에서 아까는 볼 수 없었던 Busy 컨트롤이 보입니다.
리스트박스와 콤보박스가 시간이 지나면서 채워지는 것을 바로바로 확인할 수 있습니다. 물론 Busy 컨트롤은 계속 떠있는 중이구요
모든 데이터를 출력한 후에는 Busy 컨트롤이 숨겨집니다.
이렇게 간단하게 async/await를 이용하도록 메소드를 변경하면, UI Freeze 문제를 쉽게 해결할 수 있습니다.
이 방법은 WPF, WinForm 모두 사용할 수 있으니 꼭 활용하시면 좋겠습니다.
Async/await 프로그래밍에 대한 더 자세한 사항은 여기를 참고하시기 바랍니다.
3. 소스
WpfTest/EventAsyncSample at master · kaki104/WpfTest (github.com)
첫댓글