咨詢區(qū)
-
Philippe Paré:
長(zhǎng)話短說(shuō),我需要向 tcp server
發(fā)起幾個(gè)異步的 request 請(qǐng)求,同時(shí)我的client只能用同步阻塞UI線程的方式進(jìn)行網(wǎng)絡(luò)請(qǐng)求,因?yàn)槭钱惒桨l(fā)起,多個(gè)請(qǐng)求可能會(huì)出現(xiàn)并行請(qǐng)求 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;
}
}
但是上面的代碼會(huì)拋出下面的異常:
error CS1996: Cannot await in the body of a lock statement
編譯器不允許在這里使用 lock ,但我只能這樣來(lái)強(qiáng)迫 request 請(qǐng)求串行,請(qǐng)問(wèn)我該如何實(shí)現(xiàn)?
回答區(qū)
-
Jared Moore:
要想在異步中實(shí)現(xiàn)串行同步,可以使用 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:
你所遇到的問(wèn)題,其實(shí) Nito.AsyncEx
早已經(jīng)幫你解決了,它是一個(gè) Nuget 上非常有名的異步擴(kuò)展庫(kù),很多的開(kāi)發(fā)者也都是從用 AsyncLock
開(kāi)始的,使用方式和同步模式的 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));
}
}
更多的內(nèi)容,可以參考 Github: https://github.com/StephenCleary/AsyncEx
點(diǎn)評(píng)區(qū)
AsyncEx 確實(shí)是一個(gè)非常