我刚刚写了以下代码
public void Save()
{
while (this.IsAsyncInProcess)
Thread.Sleep(100);
this.customer.OrderCount = this.orders.Count();
this.customer.OrderTotal = this.orders.Sum(o => x.Total);
this.customerRepo.Save();
}
public async Task LoadAsync()
{
this.IsAsyncInProcess = true;
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
this.IsAsyncInProcess = false;
}
现在我有一个经典的死锁,因为在
this.orders
完成后,它会等待 gui 线程恢复以将 this.IsAsyncInProcess
设置为 false
。但是,Save()
里面的 gui 线程很忙现在我将
LoadAsync
重构为public async Task LoadAsync()
{
await Task.Run(async () =>
{
this.IsAsyncInProcess = true;
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
this.IsAsyncInProcess = false;
});
}
出于兼容性原因,我不能仅仅将
Save
重构为 SaveAsync
。有没有更好的方法来实现这一点,而不使用
Task.Run
? 最佳答案
您可以使用异步锁定。如果您无法更改 Save 的签名,那么您可以代理到异步本地函数。
static SemaphoreSlim sem = new SemaphoreSlim(1,1);
public void Save()
{
SaveAsync();
public async Task SaveAsync()
{
await sem.WaitAsync();
try{
this.customer.OrderCount = this.orders.Count();
this.customer.OrderTotal = this.orders.Sum(o => x.Total);
this.customerRepo.Save();
}finally{
sem.Release();
}
}
}
public async Task LoadAsync()
{
await sem.WaitAsync();
try{
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
}finally{
sem.Release();
}
}
甚至更好地创建自己的异步锁
static SemaphoreSlim sem = new SemaphoreSlim(1,1);
public static async Task<IDisposable> LockAsync(){
await sem.WaitAsync();
return Disposable.Create(()=>sem.Release());
}
public void Save()
{
SaveAsync();
public async Task SaveAsync()
{
using(await LockAsync()){
this.customer.OrderCount = this.orders.Count();
this.customer.OrderTotal = this.orders.Sum(o => x.Total);
this.customerRepo.Save();
}
}
}
public async Task LoadAsync()
{
using(await LockAsync()){
this.customer = await this.customerRepo.GetCustomerAsync(...);
this.orders = await this.customerRepo.GetOrdersAsync(...);
}
}
关于c# - 重构以从我的代码中删除 Taks.Run,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45791550/