Vorrei chiederti a tuo parere sull'architettura corretta quando utilizzarla Task.Run
. Sto riscontrando un'interfaccia utente ritardata nella nostra applicazione WPF .NET 4.5 (con framework Caliburn Micro).
Fondamentalmente lo sto facendo (frammenti di codice molto semplificati):
public class PageViewModel : IHandle<SomeMessage>
{
...
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
// Makes UI very laggy, but still not dead
await this.contentLoader.LoadContentAsync();
HideLoadingAnimation();
}
}
public class ContentLoader
{
public async Task LoadContentAsync()
{
await DoCpuBoundWorkAsync();
await DoIoBoundWorkAsync();
await DoCpuBoundWorkAsync();
// I am not really sure what all I can consider as CPU bound as slowing down the UI
await DoSomeOtherWorkAsync();
}
}
Dagli articoli / video che ho letto / visto, so che await
async
non è necessariamente in esecuzione su un thread in background e per iniziare a lavorare in background devi avvolgerlo con waitit Task.Run(async () => ... )
. L'utilizzo async
await
non blocca l'interfaccia utente, ma è ancora in esecuzione sul thread dell'interfaccia utente, quindi è in ritardo.
Qual è il posto migliore dove posizionare Task.Run?
Dovrei solo
Termina la chiamata esterna perché si tratta di un lavoro di threading inferiore per .NET
o dovrei avvolgere solo i metodi associati alla CPU internamente in esecuzione in
Task.Run
quanto ciò lo rende riutilizzabile per altri luoghi? Non sono sicuro qui se iniziare il lavoro sui thread di sfondo in profondità nel core sia una buona idea.
Annuncio (1), la prima soluzione sarebbe così:
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
await Task.Run(async () => await this.contentLoader.LoadContentAsync());
HideLoadingAnimation();
}
// Other methods do not use Task.Run as everything regardless
// if I/O or CPU bound would now run in the background.
Annuncio (2), la seconda soluzione sarebbe così:
public async Task DoCpuBoundWorkAsync()
{
await Task.Run(() => {
// Do lot of work here
});
}
public async Task DoSomeOtherWorkAsync(
{
// I am not sure how to handle this methods -
// probably need to test one by one, if it is slowing down UI
}
await Task.Run(async () => await this.contentLoader.LoadContentAsync());
dovrebbe essere semplicementeawait Task.Run( () => this.contentLoader.LoadContentAsync() );
. AFAIK non guadagni nulla aggiungendo un secondoawait
easync
dentroTask.Run
. E poiché non stai passando parametri, questo semplifica leggermente di piùawait Task.Run( this.contentLoader.LoadContentAsync );
.