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 asyncne 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 awaitne 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.Runcar 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 secondeawaitet à l'asyncintérieurTask.Run. Et puisque vous ne passez pas de paramètres, cela simplifie un peu plusawait Task.Run( this.contentLoader.LoadContentAsync );.