[英]How to make asynchronous methods that use a queue thread safe
我有一个服务,确保同时显示一个弹出窗口。 AddPopupAsync
可以同时调用,即弹出窗口打开而另外10个AddPopupAsync
请求AddPopupAsync
。代码:
public async Task<int> AddPopupAsync(Message message)
{
//[...]
while (popupQueue.Count != 0)
{
await popupQueue.Peek();
}
return await Popup(interaction);
}
但是我可以发现由于缺乏线程安全而可能发生的两件不必要的事情:
Popup方法与TaskCompletionSource
一起使用,在调用其SetResult
方法之前,调用popupQueue.Dequeue()
。
我想考虑使用ConcurrentQueue
中的原子TryPeek
来使#1线程安全:
do
{
Task<int> result;
bool success = popupQueue.TryPeek(out result);
if (!success) break;
await result;
}
while (true);
然后我读到了AsyncProducerConsumerCollection,但我不确定这是否是最简单的解决方案。
如何以简单的方式确保线程安全? 谢谢。
要简单地添加线程安全性,您应该使用ConcurrentQueue
。 它是队列的线程安全实现,您可以像使用队列一样使用它而不必担心并发。
但是,如果你想有一个队列,你可以await
异步(这意味着你不是忙等待或阻塞的线程在等待),你应该使用TPL数据流的BufferBlock
这是非常相似的AsyncProducerConsumerCollection
通过MS你只已经实现了:
var buffer = new BufferBlock<int>();
await buffer.SendAsync(3); // Instead of enqueue.
int item = await buffer.ReceiveAsync(); // instead of dequeue.
ConcurrentQueue
对于线程安全性很好,但在高级别的争用中是浪费的。 BufferBlock
不仅是线程安全的,它还为您提供异步协调(通常在消费者和生产者之间)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.