不允许异步锁定

时间:2015-08-19 01:08:13

标签: c# async-await tcpclient

基本上,我想向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;
    }
}

我确信这不是一个好用的锁,但它是我能想到的唯一方法,可以让电话等待轮到他们。有没有我可以用来实现这种行为的对象?我认为Monitor会是一样的,所以我没有尝试过(我知道他们是多线程的东西,但这些都是我熟悉的......)

2 个答案:

答案 0 :(得分:32)

看起来你遇到的问题是线程在获取锁时会阻塞,所以你的方法不是完全异步的。要解决此问题,您可以使用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();
    }
}

答案 1 :(得分:10)

NuGet软件包Nito.AsyncEx已经彻底解决了这个问题,截至2015年8月,该软件包的下载次数已超过50,000次。

来自自述文件:

  

AsyncEx async / await的辅助库。

     

支持.NET 4.5 / 4.0,iOS,Android,Windows Store 8.0,Windows Phone   Silverlight 8.0 / 7.5,Windows Phone应用程序8.1,Silverlight   5.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));
  }
}

请参阅C# source code on GitHub或安装NuGet包Nito.AsyncEx