Я хотів би поцікавитись вашою думкою щодо правильної архітектури, коли користуватися 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
це не обов'язково працює на фоновій нитці, і щоб розпочати роботу на задньому плані, потрібно обернути її в очікуванні 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 );
.