Partager via


Assurer la réactivité du thread de l’interface utilisateur

Les utilisateurs s’attendent à ce qu’une application reste réactive pendant son calcul, quel que soit le type d’ordinateur. Cela signifie différentes choses pour différentes applications. Pour certains, cela se traduit par une physique plus réaliste, le chargement de données à partir d’un disque ou du web plus rapidement, la présentation rapide de scènes complexes et la navigation entre les pages, la recherche de directions dans un alignement ou le traitement rapide des données. Quel que soit le type de calcul, les utilisateurs veulent que leur application agisse sur leur entrée et élimine les instances où elle apparaît sans réponse alors qu’elle « pense ».

Votre application est pilotée par les événements, ce qui signifie que votre code fonctionne en réponse à un événement, puis qu’il est inactif jusqu’à la prochaine. Le code de plateforme pour l’interface utilisateur (disposition, entrée, déclenchement d’événements, etc.) et le code de votre application pour l’interface utilisateur sont tous exécutés sur le même thread d’interface utilisateur. Une seule instruction peut s’exécuter sur ce thread à la fois. Par conséquent, si le code de votre application prend trop de temps pour traiter un événement, l’infrastructure ne peut pas exécuter la disposition ou déclencher de nouveaux événements représentant l’interaction utilisateur. La réactivité de votre application est liée à la disponibilité du thread d’interface utilisateur pour traiter le travail.

Vous devez utiliser le thread d’interface utilisateur pour apporter presque toutes les modifications au thread d’interface utilisateur, notamment la création de types d’interface utilisateur et l’accès à leurs membres. Vous ne pouvez pas mettre à jour l’interface utilisateur à partir d’un thread d’arrière-plan, mais vous pouvez y publier un message avec CoreDispatcher.RunAsync pour provoquer l’exécution du code.

Note L’une des exceptions est qu’il existe un thread de rendu distinct qui peut appliquer des modifications d’interface utilisateur qui n’affectent pas la façon dont l’entrée est gérée ou la disposition de base. Par exemple, de nombreuses animations et transitions qui n’affectent pas la disposition peuvent s’exécuter sur ce thread de rendu.

Retarder l'instanciation de l'élément

Certaines des étapes les plus lentes d’une application peuvent inclure le démarrage et le basculement de vues. Ne faites pas plus de travail que nécessaire pour afficher l’interface utilisateur que l’utilisateur voit initialement. Par exemple, ne concevez pas l'interface utilisateur pour une UI à dévoilement progressif et le contenu des fenêtres contextuelles.

CoreDispatcher.RunIdleAsync files d’attente fonctionnent pour que le thread d’interface utilisateur traite lorsqu’il n’est pas occupé.

Utiliser des API asynchrones

Pour aider à maintenir la réactivité de votre application, la plateforme fournit des versions asynchrones de plusieurs de ses API. Une API asynchrone garantit que votre thread d’exécution actif ne bloque jamais pendant une durée importante. Lorsque vous appelez une API à partir du thread d’interface utilisateur, utilisez la version asynchrone si elle est disponible. Pour plus d'informations sur la programmation avec des modèles asynchrones , consultez la programmation asynchrone ,, ou la façon d'appeler des API asynchrones en C# ou Visual Basic .

Décharger le travail sur des threads d’arrière-plan

Écrivez des gestionnaires d’événements pour retourner rapidement. Lorsqu'un volume de travail non trivial doit être accompli, effectuez-le en arrière-plan et revenez.

Vous pouvez planifier le travail de manière asynchrone à l’aide de l’opérateur Await en C#, de l’opérateur Await en Visual Basic ou des délégués en C++. Toutefois, cela ne garantit pas que le travail que vous planifiez s’exécutera sur un thread d’arrière-plan. La plupart des API de la plateforme Windows universelle (UWP) planifient le travail dans le thread en arrière-plan pour vous, mais si vous appelez votre code d’application à l’aide uniquement de await ou d’un délégué, vous exécutez ce délégué ou cette méthode sur le thread de l’interface utilisateur. Vous devez indiquer explicitement quand vous souhaitez exécuter votre code d’application sur un thread d’arrière-plan. En C# et Visual Basic, vous pouvez effectuer cette opération en passant du code à Task.Run.

N’oubliez pas que les éléments de l’interface utilisateur peuvent uniquement être accessibles à partir du thread d’interface utilisateur. Utilisez le thread d’interface utilisateur pour accéder aux éléments de l’interface utilisateur avant de lancer le travail en arrière-plan et/ou utiliser CoreDispatcher.RunAsync ou CoreDispatcher.RunIdleAsync sur le thread d’arrière-plan.

Un exemple de travail qui peut être effectué sur un thread d’arrière-plan est le calcul de l’IA de l’ordinateur dans un jeu. Le code qui calcule le prochain déplacement de l’ordinateur peut prendre beaucoup de temps pour s’exécuter.

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

Dans cet exemple, le gestionnaire NextMove_Click retourne au attendre afin de maintenir le thread d’interface utilisateur réactif. Mais l'exécution reprend dans ce gestionnaire une fois que ComputeNextMove (qui s'exécute sur un thread d'arrière-plan) est terminée. Le code restant dans le gestionnaire met à jour l’interface utilisateur avec les résultats.

Remarque Il existe également une API ThreadPool et une API ThreadPoolTimer pour l'UWP, qui peuvent être utilisées pour des scénarios similaires. Pour plus d'informations, consultez Threading et programmation asynchrone.