基本上,我想向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会是一样的,所以我没有尝试过(我知道他们是多线程的东西,但这些都是我熟悉的......)
答案 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
。