不允许异步锁

本文关键字:异步 不允许 | 更新日期: 2023-09-27 18:08:32

基本上,我想向tcp服务器发出多个异步请求。我目前有一个工作客户端,它只是同步的,并且在每个网络调用上阻塞UI。由于多个请求可能几乎同时发生,所以我尝试这样做:

private object readonly readLock = new object(); 
public async Task UpdateDetailsAsync()
{
    //I want every request to wait their turn before requesting (using the connection) 
    //to prevent a read call from catching any data from another request
    lock (readLock)
    {
        Details details = await connection.GetDetailsAsync();
        detailsListBox.Items = details;
    }
}

我确信这不是锁的好用法,但这是我能想到的唯一可以使调用等待轮到它们的方法。有什么东西可以让我实现这种行为吗?我认为监视器将是相同的,所以我没有尝试(我知道他们是多线程的东西,但这就是我所熟悉的…)

不允许异步锁

看起来您遇到的问题是线程在获取锁时会阻塞,因此您的方法不是完全异步的。要解决这个问题,可以使用SemaphoreSlim。WaitAsync

private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1); 
public async Task UpdateDetailsAsync()
{
    //I want every request to wait their turn before requesting (using the connection) 
    //to prevent a read call from catching any data from another request
    await readLock.WaitAsync();
    try
    {
        Details details = await connection.GetDetailsAsync();
        detailsListBox.Items = details;
    }
    finally
    {
        readLock.Release();
    }
}

这个问题已经被NuGet软件包Nito.AsyncEx巧妙地解决了,截至2015年8月,该软件包的下载量已超过5万次。

从自述:

async/await的辅助库。#

支持。net 4.5/4.0, iOS, Android, Windows Store 8.0, Windows PhoneSilverlight 8.0/7.5, Windows Phone Applications 8.1, Silverlight5.0/4.0及其所有可移植库。

(剪)

# AsyncLock #

许多开发人员开始使用这个库来实现AsyncLock,这是一种异步兼容的互斥机制。使用AsyncLock很简单:

private readonly AsyncLock _mutex = new AsyncLock();
public async Task UseLockAsync()
{
  // AsyncLock can be locked asynchronously
  using (await _mutex.LockAsync())
  {
    // It's safe to await while the lock is held
    await Task.Delay(TimeSpan.FromSeconds(1));
  }
}

在GitHub上查看c#源代码或安装NuGet包Nito.AsyncEx