사용자는 컴퓨터 유형에 관계없이 계산을 수행하는 동안 앱이 응답성을 유지할 것으로 예상합니다. 이는 실제 물리학 제공, 디스크 또는 웹에서 데이터 로드, 복잡한 장면 표시, 페이지 간 탐색 또는 데이터 처리 등 다양한 앱에 대해 서로 다른 것을 의미합니다. 계산 유형에 관계없이 사용자는 앱이 입력에 따라 작동하고 응답하지 않는 것처럼 보이는 인스턴스를 제거하기를 원합니다.
앱은 이벤트 기반입니다. 코드는 이벤트에 대한 응답으로 작업을 수행한 다음 다음 이벤트까지 유휴 상태입니다. UI에 대한 플랫폼 코드(레이아웃, 입력, 이벤트 발생) 및 앱의 UI 코드는 모두 동일한 UI 스레드에서 실행됩니다. 한 번에 하나의 명령만 해당 스레드에서 실행되므로 앱 코드가 이벤트를 처리하는 데 너무 오래 걸리는 경우 프레임워크는 레이아웃을 실행하거나 새 이벤트를 발생할 수 없습니다. 앱의 응답성은 작업을 처리하는 UI 스레드의 가용성과 관련이 있습니다.
UI 스레드를 사용하여 UI 요소를 거의 모두 변경해야 합니다. 백그라운드 스레드에서 UI를 업데이트할 수는 없지만 DispatcherQueue.TryEnqueue 를 사용하여 메시지를 게시하여 코드가 실행되도록 할 수 있습니다.
Important
WinUI 3 데스크톱 앱에서 UWP DispatcherQueue대신 사용합니다CoreDispatcher. 창의 DispatcherQueue 속성 또는 DispatcherQueue.GetForCurrentThread().를 통해 디스패처 큐에 액세스합니다.
메모
별도의 렌더링 스레드는 입력 처리 방법 또는 기본 레이아웃에 영향을 주지 않는 UI 변경 내용을 적용할 수 있습니다. 예를 들어 레이아웃에 영향을 주지 않는 많은 애니메이션 및 전환은 이 렌더링 스레드에서 실행할 수 있습니다.
요소 인스턴스화 지연
앱에서 가장 느린 단계 중 일부에는 시작 및 전환 보기가 포함됩니다. 사용자가 처음에 보는 UI를 가져오는 데 필요한 것보다 더 많은 작업을 수행하지 마세요. 예를 들어 점진적으로 공개되는 콘텐츠 또는 팝업 콘텐츠에 대한 UI를 만들지 마세요.
- x:Load 특성을 사용하여 요소를 지연 인스턴스화합니다.
- 프로그래밍 방식으로 주문형 트리에 요소를 삽입합니다.
UI 스레드가 바쁘지 않을 때 처리할 작업을 낮은 우선 순위로 대기열에 추가하려면 DispatcherQueue.TryEnqueue를 사용합니다.
비동기 API 사용하기
앱의 응답성을 유지하려면 사용 가능한 경우 비동기 버전의 API를 사용합니다. 비동기 API를 사용하면 활성 실행 스레드가 상당한 시간 동안 차단되지 않습니다. UI 스레드에서 API를 호출하는 경우 비동기 버전이 있는 경우 항상 사용합니다.
백그라운드 스레드로 작업 오프로드
신속하게 반환할 이벤트 처리기를 작성합니다. 상당한 작업을 수행해야 하는 경우에는 백그라운드 스레드에서 실행하도록 예약하고 반환하세요.
C#에서 연산자를 사용하여 작업을 비동기적으로 예약할 await 수 있습니다. 그러나 await 작업이 백그라운드 스레드에서 실행되도록 보장하지는 않습니다. 많은 Windows 앱 SDK API는 백그라운드 스레드에서 작업을 예약하지만 앱 코드만 await사용하여 호출하는 경우 UI 스레드에서 해당 메서드를 실행합니다. 백그라운드 스레드에서 앱 코드를 명시적으로 실행해야 합니다. C#에서 Task.Run에 코드를 전달하여 이 작업을 수행합니다.
UI 스레드에서 UI 요소에만 액세스할 수 있습니다. 백그라운드 작업을 시작하기 전에 UI 스레드를 사용하여 UI 요소에 액세스하거나 백그라운드 스레드에서 UI 업데이트를 다시 UI 스레드에 게시하는 데 사용합니다 DispatcherQueue.TryEnqueue .
public sealed partial class MainWindow : Window
{
// Declared in MainWindow.xaml as x:Name="statusText".
private TextBlock statusText;
private async void NextMove_Click(object sender, RoutedEventArgs e)
{
// The await causes the handler to return immediately.
await Task.Run(() => ComputeNextMove());
// Now update the UI with the results.
// This code runs on the UI thread after ComputeNextMove completes.
statusText.Text = "Move computed.";
}
private void ComputeNextMove()
{
// Perform background work here.
// Don't directly access UI elements from this method.
}
}
이 예제에서 NextMove_Click 처리기는 UI 스레드가 계속 응답할 수 있도록 await에서 반환합니다.
ComputeNextMove(백그라운드 스레드에서 실행됨)가 완료되면 해당 핸들러에서 실행이 다시 이어지고, 나머지 코드는 그 결과를 사용해 UI를 업데이트합니다.
관련 콘텐츠
Windows developer