
咨詢區
-
Philippe Paré:
長話短說,我需要向 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 請求串行,請問我該如何實現?
回答區
-
Jared Moore:
要想在異步中實現串行同步,可以使用 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();
}
}
-
Contango:
你所遇到的問題,其實 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 確實是一個非常