Me gustaría preguntarle su opinión sobre la arquitectura correcta cuando usarla Task.Run
. Estoy experimentando una interfaz de usuario lenta en nuestra aplicación WPF .NET 4.5 (con el marco Caliburn Micro).
Básicamente estoy haciendo (fragmentos de código muy simplificados):
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();
}
}
De los artículos / videos que leí / vi, sé que await
async
no necesariamente se ejecuta en un hilo de fondo y para comenzar a trabajar en segundo plano, debe envolverlo con esperar Task.Run(async () => ... )
. El uso async
await
no bloquea la interfaz de usuario, pero aún se está ejecutando en el subproceso de la interfaz de usuario, por lo que la hace lenta.
¿Dónde está el mejor lugar para poner Task.Run?
Debería solo
Ajuste la llamada externa porque esto es menos trabajo de subprocesamiento para .NET
, ¿o debería ajustar solo los métodos vinculados a la CPU que se ejecutan internamente,
Task.Run
ya que esto lo hace reutilizable para otros lugares? No estoy seguro aquí si comenzar a trabajar en subprocesos de fondo en el núcleo es una buena idea.
Anuncio (1), la primera solución sería así:
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.
Anuncio (2), la segunda solución sería así:
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());
simplemente debería serawait Task.Run( () => this.contentLoader.LoadContentAsync() );
. AFAIK no ganas nada agregando un segundoawait
yasync
adentroTask.Run
. Y como no estás pasando parámetros, eso se simplifica un poco másawait Task.Run( this.contentLoader.LoadContentAsync );
.