共用方式為


讓UI線程保持回應

使用者預期無論計算機類型為何,應用程式都會在計算時保持回應。 對於不同的應用程式,這代表不同的意義。 對於某些人來說,這可以實現更逼真的物理效果、更快速地從磁碟或網路載入資料、快速呈現複雜的場景,順暢地在頁面間瀏覽、快速找到路線或迅速處理資料。 無論計算類型為何,使用者都希望其應用程式在其輸入上採取行動,並排除在「思考」時其看起來沒有回應的實例。

您的應用程式是事件驅動,這表示您的程式代碼會執行工作以回應事件,然後閒置直到下一個事件為止。 UI 的平台程式代碼(配置、輸入、引發事件等)和您的應用程式 UI 程式代碼全都在同一個 UI 線程上執行。 一次只能有一個指令在該線程上執行,因此如果您的應用程式程式代碼處理事件的時間太長,則架構無法執行配置或引發代表用戶互動的新事件。 應用程式的回應性與UI線程的可用性有關,以處理工作。

您必須使用UI線程,對UI線程進行幾乎所有的變更,包括建立UI類型及存取其成員。 您無法從背景執行緒更新 UI,但您可以使用 CoreDispatcher.RunAsync 將訊息傳送至 UI 執行緒,這樣 的程式碼就會在那裡執行。

注意 有一個例外,那就是有一個獨立的呈現執行緒可以進行UI變更,而不會影響如何處理輸入或基本佈局。 例如,許多不會影響版面配置的動畫和轉換都可以在此轉譯線程上執行。

延遲元素實例化

應用程式中一些最慢的階段可能包括啟動和切換檢視。 不要執行比使用者一開始看到UI所需的更多工作。 例如,請勿為漸進式顯示的 UI 和彈出視窗的內容建立 UI。

CoreDispatcher.RunIdleAsync 佇列可讓 UI 線程在空閒時進行處理。

使用非同步 API

為了協助讓應用程式保持回應,平臺會提供許多 API 的異步版本。 異步 API 可確保作用中的執行線程永遠不會長時間封鎖。 當您從 UI 線程呼叫 API 時,如果有可用的異步版本,請使用異步版本。 如需使用 異步 模式進行程式設計的詳細資訊,請參閱 異步程式設計 或在 C# 或 Visual Basic中呼叫異步 API

將工作轉移至背景執行緒

撰寫事件處理程式以快速傳回。 在需要大量工作的情況下,請在背景執行緒上排程並返回。

您可以使用 C# 中的 await 運算子、Visual Basic 中的 Await 運算子或 C++ 中的委派,以異步方式排程工作。 但這不保證您排程的工作將在背景線程上執行。 許多通用 Windows 平台 (UWP) API 會為您在背景執行緒中安排工作,但是如果您只使用 await 或委派來呼叫應用程式代碼,您會在 UI 執行緒上執行該委派或方法。 您必須在背景線程上明確說明何時要執行應用程式程序代碼。 在 C# 和 Visual Basic 中,您可以將程式代碼傳遞至 Task.Run 來完成這項作業。

請記住,UI 元素只能從UI線程存取。 在啟動背景工作之前,請使用 UI 執行緒來存取 UI 元素,並且/或在背景執行緒上使用 CoreDispatcher.RunAsyncCoreDispatcher.RunIdleAsync

可以在背景線程上執行的工作範例,就是運算遊戲中的電腦 AI。 計算計算機下一個行動的程式代碼可能需要很多時間才能執行。

public class AsyncExample
{
    private async void NextMove_Click(object sender, RoutedEventArgs e)
    {
        // The await causes the handler to return immediately.
        await System.Threading.Tasks.Task.Run(() => ComputeNextMove());
        // Now update the UI with the results.
        // ...
    }

    private async System.Threading.Tasks.Task ComputeNextMove()
    {
        // Perform background work here.
        // Don't directly access UI elements from this method.
    }
}
Public Class AsyncExample
    ' ...
    Private Async Sub NextMove_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Await Task.Run(Function() ComputeNextMove())
        ' update the UI with results
    End Sub

    Private Async Function ComputeNextMove() As Task
        ' ...
    End Function
    ' ...
End Class

在此範例中,NextMove_Click 處理程式會傳回 await,以便讓UI線程保持回應。 但在 ComputeNextMove (在背景執行緒上執行)完成之後,執行會再次在該處理程式中繼續。 處理程式中的其餘程式代碼會使用結果來更新UI。

注意UWP 也有一個 ThreadPool 和 ThreadPoolTimer API,可用於類似的案例。 如需詳細資訊,請參閱 線程和異步程序設計