Sdílet prostřednictvím


Udržujte vlákno uživatelského rozhraní responsivní

Uživatelé očekávají, že aplikace zůstane responzivní, i když bude provádět výpočty bez ohledu na typ počítače. To znamená různé věci pro různé aplikace. Pro některé to znamená poskytování realističtější fyziky, rychlejší načítání dat z disku nebo webu, rychlé prezentování složitých scén a rychlou navigaci mezi stránkami, okamžité vyhledání trasy nebo rychlé zpracování dat. Bez ohledu na typ výpočtu chtějí uživatelé, aby aplikace fungovala na vstupu a eliminovala instance, ve kterých se zdá, že nereaguje, zatímco si myslí.

Aplikace je řízená událostmi, což znamená, že váš kód funguje v reakci na událost a pak bude nečinný až do dalšího. Kód platformy pro uživatelské rozhraní (rozložení, vstup, vyvolávání událostí atd.) a kód aplikace pro uživatelské rozhraní se spouští ve stejném vlákně uživatelského rozhraní. Na daném vlákně může být spuštěna pouze jedna instrukce, takže pokud zpracování události trvá příliš dlouho, architektura nemůže spustit rozložení nebo vyvolat nové události představující interakci uživatele. Rychlost odezvy aplikace souvisí s dostupností vlákna uživatelského rozhraní pro zpracování.

Je potřeba použít vlákno uživatelského rozhraní k provedení téměř všech změn, včetně vytváření typů uživatelského rozhraní a přístupu k jejich členům. Uživatelské rozhraní nemůžete aktualizovat z vlákna na pozadí, ale můžete do něj publikovat zprávu pomocí CoreDispatcher.RunAsync , aby se tam spustil kód.

Poznámka Jedinou výjimkou je, že existuje samostatné vlákno vykreslení, které může použít změny uživatelského rozhraní, které neovlivní způsob zpracování vstupu nebo základní rozložení. Například mnoho animací a přechodů, které nemají vliv na rozložení, se může spustit v tomto vlákně vykreslení.

Zpoždění vytvoření instance prvku

Mezi nejpomalejší fáze v aplikaci patří spuštění a přepínání zobrazení. Neproveďte více práce, než je nutné k vyvolání uživatelského rozhraní, které uživatel na začátku vidí. Například nevytvářejte uživatelské rozhraní s postupným odkrýváním prvků a obsah vyskakovacích oken.

  • Pro opožděné vytvoření instance prvků použijte atribut x:Load nebo x:DeferLoadStrategy.
  • Vkládejte prvky do stromu programově na vyžádání.

CoreDispatcher.RunIdleAsync fronty úloh jsou pro uživatelské rozhraní ke zpracování, pokud není zaneprázdněno.

Použití asynchronních rozhraní API

Aby byla aplikace responzivní, poskytuje platforma asynchronní verze mnoha jeho rozhraní API. Asynchronní rozhraní API zajišťuje, že vaše aktivní prováděcí vlákno se nikdy po dlouhou dobu nezablokuje. Při volání rozhraní API z vlákna uživatelského rozhraní použijte asynchronní verzi, pokud je k dispozici. Další informace o programování pomocí asynchronních vzorů najdete v tématu Asynchronní programování nebo Volání asynchronních rozhraní API v jazyce C# nebo Visual Basic.

Přenést práci na vlákna na pozadí

Napište obslužné rutiny událostí, které se mají rychle vrátit. V případech, kdy je potřeba provést jiné než triviální množství práce, naplánujte ji na vlákno na pozadí a vraťte se.

Práci můžete naplánovat asynchronně pomocí operátoru await v jazyce C#, operátoru Await v jazyce Visual Basic nebo delegátů v jazyce C++. To ale nezaručuje, že práce, kterou plánujete, se spustí na vlákně na pozadí. Mnoho rozhraní API univerzální platformy Windows (UWP) plánuje práci na pozadí pro vás, ale pokud voláte kód své aplikace pouze pomocí await nebo delegate, spustíte tento delegate nebo metodu na vlákně uživatelského rozhraní. Musíte explicitně říct, kdy chcete spustit kód aplikace ve vlákně na pozadí. V jazyce C# a Visual Basic toho můžete dosáhnout předáním kódu do Task.Run.

Mějte na paměti, že k prvkům uživatelského rozhraní lze přistupovat pouze z vlákna uživatelského rozhraní. Použijte vlákno uživatelského rozhraní pro přístup k prvkům uživatelského rozhraní před spuštěním práce na pozadí a/nebo použijte CoreDispatcher.RunAsync nebo CoreDispatcher.RunIdleAsync na vlákně určeném pro zpracovávání úloh na pozadí.

Příkladem práce, kterou lze provést na vlákně na pozadí, je výpočet počítačové umělé inteligence ve hře. Spuštění kódu, který vypočítá další přesunutí počítače, může trvat hodně času.

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

V tomto příkladu se obslužná rutina NextMove_Click vrátí na await, aby bylo vlákno uživatelského rozhraní responzivní. Provádění se ale v této obslužné rutině znovu spustí po dokončení ComputeNextMove (který se spustí ve vlákně na pozadí). Zbývající kód v obslužné rutině aktualizuje uživatelské rozhraní s výsledky.

Poznámka Existuje také ThreadPool a rozhraní API ThreadPoolTimer pro UWP, které lze použít pro podobné scénáře. Další informace najdete v tématu Threading a asynchronní programování.