Ich möchte Sie nach Ihrer Meinung zur richtigen Architektur fragen Task.Run
. In unserer WPF .NET 4.5-Anwendung (mit Caliburn Micro Framework) tritt eine verzögerte Benutzeroberfläche auf.
Grundsätzlich mache ich (sehr vereinfachte Code-Schnipsel):
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();
}
}
Aus den Artikeln / Videos, die ich gelesen / gesehen habe, weiß ich, dass sie await
async
nicht unbedingt in einem Hintergrund-Thread ausgeführt werden. Um mit der Arbeit im Hintergrund zu beginnen, müssen Sie sie mit Warten umhüllen Task.Run(async () => ... )
. Die Verwendung async
await
blockiert die Benutzeroberfläche nicht, wird jedoch im UI-Thread ausgeführt, sodass sie verzögert wird.
Wo kann Task.Run am besten platziert werden?
Soll ich nur
Schließen Sie den äußeren Aufruf ab, da dies für .NET weniger Threading-Arbeit bedeutet
, oder sollte ich nur CPU-gebundene Methoden einbinden, die intern ausgeführt werden,
Task.Run
da dies die Wiederverwendung für andere Orte ermöglicht? Ich bin mir hier nicht sicher, ob es eine gute Idee ist, mit der Arbeit an Hintergrundthreads tief im Kern zu beginnen.
Anzeige (1), die erste Lösung wäre wie folgt:
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.
Anzeige (2), die zweite Lösung wäre wie folgt:
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());
einfach seinawait Task.Run( () => this.contentLoader.LoadContentAsync() );
. AFAIK Sie gewinnen nichts, indem Sie eine Sekundeawait
undasync
innen hinzufügenTask.Run
. Und da Sie keine Parameter übergeben, vereinfacht sich dies etwas mehrawait Task.Run( this.contentLoader.LoadContentAsync );
.