长话短说,我需要向 tcp server
发起几个异步的 request 请求,同时我的client只能用同步阻塞UI线程的方式进行网络请求,因为是异步发起,多个请求可能会出现并行请求 tcp server 的情况,所以我尝试用 lock 限定 。
private readonly object 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;
}
}
但是上面的代码会抛出下面的异常:
error CS1996: Cannot await in the body of a lock statement
编译器不允许在这里使用 lock ,但我只能这样来强迫 request 请求串行,请问我该如何实现?
要想在异步中实现串行同步,可以使用 C# 新提供的 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();
}
}
你所遇到的问题,其实 Nito.AsyncEx
早已经帮你解决了,它是一个 Nuget 上非常有名的异步扩展库,很多的开发者也都是从用 AsyncLock
开始的,使用方式和同步模式的 lock 很相似,参考如下代码:
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: https://github.com/StephenCleary/AsyncEx
AsyncEx 确实是一个非常