Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Gli utenti si aspettano che l'app rimanga reattiva durante l'esecuzione del calcolo, indipendentemente dal tipo di computer. Ciò significa cose diverse per app diverse, fornendo fisica realistica, caricando i dati dal disco o dal Web, presentando scene complesse, spostandosi tra pagine o elaborando i dati. Indipendentemente dal tipo di calcolo, gli utenti vogliono che l'app agisca sul proprio input ed elimina le istanze in cui non risponde.
L'app è guidata dagli eventi: il codice esegue il lavoro in risposta a un evento e quindi rimane inattiva fino all'evento successivo. Codice della piattaforma per l'interfaccia utente (layout, input, generazione di eventi) e il codice dell'app per l'interfaccia utente vengono eseguiti nello stesso thread dell'interfaccia utente. Solo un'istruzione viene eseguita su tale thread alla volta, quindi se il codice dell'app richiede troppo tempo per elaborare un evento, il framework non può eseguire il layout o generare nuovi eventi. La velocità di risposta dell'app è correlata alla disponibilità del thread dell'interfaccia utente per elaborare il lavoro.
È necessario usare il thread dell'interfaccia utente per apportare quasi tutte le modifiche agli elementi dell'interfaccia utente. Non è possibile aggiornare l'interfaccia utente da un thread in background, ma è possibile pubblicarvi un messaggio con DispatcherQueue.TryEnqueue per causare l'esecuzione del codice.
Importante
Nelle app desktop WinUI 3 usare DispatcherQueue anziché la piattaforma UWP CoreDispatcher. Accedi alla coda del dispatcher tramite la proprietà DispatcherQueue della finestra o DispatcherQueue.GetForCurrentThread().
Note
Un thread di rendering separato può applicare modifiche dell'interfaccia utente che non influiscono sulla modalità di gestione dell'input o sul layout di base. Ad esempio, molte animazioni e transizioni che non influiscono sul layout possono essere eseguite su questo thread di rendering.
Istanziazione dell'elemento Delay
Alcune delle fasi più lente di un'app includono l'avvio e il cambio di visualizzazioni. Non eseguire più operazioni del necessario per visualizzare l'interfaccia utente visualizzata inizialmente dall'utente. Ad esempio, non creare l'interfaccia utente per contenuti divulgati progressivamente o contenuti popup.
- Usare l'attributo x:Load per posticipare l'istanziazione degli elementi.
- Inserire elementi nell'albero su richiesta a livello di codice.
Usare DispatcherQueue.TryEnqueue con priorità bassa per accodare del lavoro che il thread dell'interfaccia utente elaborerà quando non è impegnato.
Usare le API asincrone
Per mantenere reattiva l'app, usa le versioni asincrone delle API quando sono disponibili. Un'API asincrona garantisce che il thread di esecuzione attivo non si blocchi mai per una quantità significativa di tempo. Quando si chiama un'API dal thread dell'interfaccia utente, usare sempre la versione asincrona, se presente.
Spostare il lavoro ai thread in background
Scrivete gestori di eventi in modo che terminino rapidamente. Quando è necessario eseguire una quantità significativa di lavoro, programmarla su un thread in background e quindi restituire.
È possibile pianificare il lavoro in modo asincrono usando l'operatore await in C#. Tuttavia, await non garantisce che il lavoro venga eseguito su un thread in background. Molte API SDK per app di Windows pianificano il lavoro in un thread in background, ma se chiami il codice dell'app usando solo await, esegui questo metodo nel thread dell'interfaccia utente. È necessario eseguire esplicitamente il codice dell'app in un thread in background. In C#, eseguire questa operazione passando il codice a Task.Run.
Tenere presente che è possibile accedere solo agli elementi dell'interfaccia utente dal thread dell'interfaccia utente. Usare il thread dell'interfaccia utente per accedere agli elementi dell'interfaccia utente prima di avviare il lavoro in background, oppure usare DispatcherQueue.TryEnqueue dal thread in background per inviare gli aggiornamenti dell'interfaccia utente al thread dell'interfaccia utente.
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.
}
}
In questo esempio, il gestore NextMove_Click restituisce il controllo in corrispondenza di await per mantenere reattivo il thread dell'interfaccia utente. L'esecuzione riprende in tale gestore dopo il completamento di ComputeNextMove (che viene eseguito su un thread in background) e il codice rimanente aggiorna l'interfaccia utente con i risultati.