我应该在存储库之类的地方使用ConfigureAwait(false)吗? [英] Should I use ConfigureAwait(false) in places like Repository?
问题描述
只需阅读有关ConfigureAwait的这篇文章,它使我想到了一个问题我已经有一段时间没有和睦了.
Just read this article about ConfigureAwait and it made me think on an issue I haven't been able to come to peace with for some time now.
请考虑以下代码.每个依赖项使用 await
进行异步调用.我担心的是,每次我们退出 await
时,它都会返回到UI线程,直到我实际上处于需要更新UI以便进行更新的顶层时,我才希望这样做减少线程上下文切换.这使我认为应该在UI下方的层中使用 ConfigureAwait(false)
,以避免不必要的 Post
的( SynchronizationContext
)到UI线程.
Consider the code below. Each dependency uses await
to make the call asynchronous. My concern is that each time we exit an await
it goes back to the UI thread and I don't want that until I'm actually at the top level where the UI needs to be updated in order to reduce thread context switching. That made me think that ConfigureAwait(false)
should be used in layers below the UI to avoid unnecessary Post
's (SynchronizationContext
) to the UI thread.
您怎么看?这是必要的还是我要离开?还是运行时会真正为我解决这个问题?
What do you think? Is this necessary or am I way off? Or will the runtime actually take care of this for me?
public class ViewModel
{
private readonly Service service;
private readonly ICommand updateCommand;
public ViewModel(Service service)
{
this.service = service;
updateCommand = new RelayCommand(UpdateUser);
}
private async void UpdateUser()
{
Cursor.ShowWait();
await service.UpdateUser(SelectedUser);
Cursor.ShowDefault();
}
}
public class Service
{
private readonly Repository repository;
public Service(Repository repository)
{
this.repository = repository;
}
public async Task UpdateUser(Model.User user)
{
var domainUser = Convert(user);
await repository.UpdateUser(domainUser);
}
}
public class Repository
{
private readonly MyDbContext context;
public Repository(MyDbContext context)
{
this.context = context;
}
public async Task UpdateUser(User user)
{
context.Users.Update(user);
await context.SaveChangesAsync();
}
}
public class MyDbContext : DbContext
{
public DbSet<User> Users { get; set; }
}
使用ConfigureAwait(false)
public class ViewModel
{
private readonly Service service;
private readonly ICommand updateCommand;
public ViewModel(Service service)
{
this.service = service;
updateCommand = new RelayCommand(UpdateUser);
}
private async void UpdateUser()
{
Cursor.ShowWait();
await service.UpdateUser(SelectedUser);
Cursor.ShowDefault();
}
}
public class Service
{
private readonly Repository repository;
public Service(Repository repository)
{
this.repository = repository;
}
public async Task UpdateUser(Model.User user)
{
var domainUser = Convert(user);
await repository.UpdateUser(domainUser).ConfigureAwait(false);
}
}
public class Repository
{
private readonly MyDbContext context;
public Repository(MyDbContext context)
{
this.context = context;
}
public async Task UpdateUser(User user)
{
context.Users.Update(user);
await context.SaveChangesAsync().ConfigureAwait(false);
}
}
public class MyDbContext : DbContext
{
public DbSet<User> Users { get; set; }
}
推荐答案
即使代码(在我看来)比没有代码要糟糕得多,也应始终在库中使用configureAwait.
You should always use configureAwait in libraries, even if the code (in my opinion) is much worse than without.