Я хотел бы спросить вас о вашем мнении о правильной архитектуре, когда использовать Task.Run
. Я испытываю медленный пользовательский интерфейс в нашем приложении WPF .NET 4.5 (с платформой Caliburn Micro).
В основном я делаю (очень упрощенные фрагменты кода):
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();
}
}
Из статей / видео, которые я прочитал / увидел, я знаю, что await
async
это не обязательно работает в фоновом потоке, и чтобы начать работу в фоновом режиме, нужно обернуть его с помощью await Task.Run(async () => ... )
. Использование async
await
не блокирует пользовательский интерфейс, но, тем не менее, он работает в потоке пользовательского интерфейса, что делает его медленным.
Где лучше всего разместить Task.Run?
Должен ли я просто
Оберните внешний вызов, потому что это менее трудоемкая работа для .NET
, или я должен обернуть только связанные с процессором методы, которые выполняются внутри,
Task.Run
поскольку это делает его многоразовым для других мест? Я не уверен, что начинать работу с фоновыми потоками в ядре - хорошая идея.
Объявление (1), первое решение будет выглядеть так:
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.
Объявление (2), второе решение будет выглядеть так:
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());
должна быть простоawait Task.Run( () => this.contentLoader.LoadContentAsync() );
. AFAIK вы ничего не получите, добавив секундуawait
иasync
внутриTask.Run
. А так как вы не передаете параметры, это немного упрощаетawait Task.Run( this.contentLoader.LoadContentAsync );
.