重构从我的代码中删除Taks.Run

时间:2017-08-21 07:32:12

标签: c# async-await

我刚写了以下代码

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。但是,gui线程在Save()

内忙碌

现在我重构了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

1 个答案:

答案 0 :(得分:2)

您可以使用异步锁定。如果您无法更改Save的签名,那么您只需代理一个异步本地函数。

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(...);
    }
}

甚至更好地创建自己的异步锁

git pull