Je voudrais vous demander votre avis sur la bonne architecture à utiliser Task.Run
. J'expérimente une interface utilisateur laggy dans notre application WPF .NET 4.5 (avec le framework Caliburn Micro).
Fondamentalement, je fais (extraits de code très simplifiés):
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();
}
}
D'après les articles / vidéos que j'ai lus / vus, je sais que cela await
async
ne fonctionne pas nécessairement sur un fil d'arrière-plan et pour commencer à travailler en arrière-plan, vous devez l'envelopper avec attendre Task.Run(async () => ... )
. L'utilisation async
await
ne bloque pas l'interface utilisateur, mais elle fonctionne toujours sur le thread d'interface utilisateur, ce qui la rend retardée.
Où est le meilleur endroit pour mettre Task.Run?
Dois-je juste
Encapsulez l'appel externe car cela représente moins de travail de threading pour .NET
, ou dois-je envelopper uniquement les méthodes liées au processeur qui s'exécutent en interne,
Task.Run
car cela les rend réutilisables pour d'autres endroits? Je ne sais pas ici si commencer à travailler sur des threads d'arrière-plan profondément enfouis est une bonne idée.
Ad (1), la première solution serait la suivante:
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.
Ad (2), la deuxième solution serait la suivante:
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());
devrait simplement êtreawait Task.Run( () => this.contentLoader.LoadContentAsync() );
. AFAIK vous ne gagnez rien en ajoutant une secondeawait
et à l'async
intérieurTask.Run
. Et puisque vous ne passez pas de paramètres, cela simplifie un peu plusawait Task.Run( this.contentLoader.LoadContentAsync );
.