不允许异步锁
Async lock not allowed
基本上,我想向 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;
}
}
我确信这不是 lock 的好用法,但这是我能想到的唯一可以让调用等待轮到它们的方法。有没有我可以用来实现这种行为的对象?我以为 Monitor 会是一样的,所以我没有尝试(我知道它们是多线程的东西,但这就是我所熟悉的......)
看起来你遇到的问题是线程在获取锁时会阻塞,所以你的方法不是完全异步的。要解决此问题,您可以使用 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 package Nito.AsyncEx
巧妙地解决了,截至 2015 年 8 月下载量已超过 50,000。
来自自述文件:
#AsyncEx A helper library for async/await.#
Supports .NET 4.5/4.0, iOS, Android, Windows Store 8.0, Windows Phone
Silverlight 8.0/7.5, Windows Phone Applications 8.1, Silverlight
5.0/4.0, and all portable libraries thereof.
[snip]
#AsyncLock#
A lot of developers start using this library for AsyncLock, an async-compatible mutual exclusion mechanism. Using AsyncLock is straightforward:
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 package Nito.AsyncEx
.
基本上,我想向 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;
}
}
我确信这不是 lock 的好用法,但这是我能想到的唯一可以让调用等待轮到它们的方法。有没有我可以用来实现这种行为的对象?我以为 Monitor 会是一样的,所以我没有尝试(我知道它们是多线程的东西,但这就是我所熟悉的......)
看起来你遇到的问题是线程在获取锁时会阻塞,所以你的方法不是完全异步的。要解决此问题,您可以使用 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 package Nito.AsyncEx
巧妙地解决了,截至 2015 年 8 月下载量已超过 50,000。
来自自述文件:
#AsyncEx A helper library for async/await.#
Supports .NET 4.5/4.0, iOS, Android, Windows Store 8.0, Windows Phone Silverlight 8.0/7.5, Windows Phone Applications 8.1, Silverlight 5.0/4.0, and all portable libraries thereof.
[snip]
#AsyncLock#
A lot of developers start using this library for AsyncLock, an async-compatible mutual exclusion mechanism. Using AsyncLock is straightforward:
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 package Nito.AsyncEx
.