C# 如何使使用队列线程的异步方法安全
我有一项服务,可以确保在同一时间只显示一个弹出窗口C# 如何使使用队列线程的异步方法安全,c#,.net,thread-safety,async-await,C#,.net,Thread Safety,Async Await,我有一项服务,可以确保在同一时间只显示一个弹出窗口AddPopupAsync可以同时调用,即打开一个弹出窗口,同时插入另10个AddPopupAsync请求。守则: public async Task<int> AddPopupAsync(Message message) { //[...] while (popupQueue.Count != 0) { await popupQueue.Peek(); } return a
AddPopupAsync
可以同时调用,即打开一个弹出窗口,同时插入另10个AddPopupAsync
请求。守则:
public async Task<int> AddPopupAsync(Message message)
{
//[...]
while (popupQueue.Count != 0)
{
await popupQueue.Peek();
}
return await Popup(interaction);
}
然后我读了一篇关于a的文章,但我不确定这是否是最简单的解决方案
如何以简单的方式确保线程安全?谢谢。要简单地添加线程安全性,您应该使用
ConcurrentQueue
。这是一个线程安全的队列实现,您可以像使用队列一样使用它,而不必担心并发性
但是,如果您想要队列,您可以异步等待
(这意味着您在等待时不忙于等待或阻塞线程),您应该使用TPL Dataflow的缓冲块
,它非常类似于仅由MS为您实现的AsyncProducerConsumerCollection
:
var buffer = new BufferBlock<int>();
await buffer.SendAsync(3); // Instead of enqueue.
int item = await buffer.ReceiveAsync(); // instead of dequeue.
var buffer=new BufferBlock();
等待缓冲区。SendAsync(3);//而不是排队。
int item=wait buffer.ReceiveAsync();//而不是排队。
ConcurrentQueue
对于线程安全性来说很好,但是在高级别争用中是浪费的BufferBlock
不仅是线程安全的,它还为您提供异步协调(通常在消费者和生产者之间)。我想您已经回答了自己的问题ConcurrentQueue
内置了您需要的功能。您当前的语义是,所有对AddPopupAsync
的调用在显示所有弹出窗口(而不仅仅是该特定调用显示的弹出窗口)之前都不会完成。你确定这就是你想要的语义吗?@Stephen Cleary因为PopupView和PopupViewModel是单例的,所以每当调用popup时,模式弹出窗口的状态都会改变。这就是我使用队列的原因。把这个UI服务当作UI的一部分来对待难道没有意义吗;i、 例如,仅从UI上下文调用AddPopupAsync
?@Stephen Cleary:如果仅从UI线程调用AddPopupAsync,则AddPopupAsync会因为wait关键字而在工作线程上运行。对吗?你想说不需要异步函数,因为AddPopupAsync中没有计算绑定工作,如果不再有异步函数,代码将是线程安全的吗?但是ConcurrentQueue并不表示使用ConcurrentQueue的代码是线程安全的,是吗(请参阅我问题中的#2)?@user4287276ConcurrentQueue
确保对其方法之一的每次调用本身是线程安全的。这不是一个锁定机制。如果您的代码需要同步,您应该使用锁
(或者异步锁
,如果合适的话)。BufferBlock没有peekmethod@ArnoldPistorius它是否有一个TryReceive
方法来接受可以用作“peek”的谓词?
var buffer = new BufferBlock<int>();
await buffer.SendAsync(3); // Instead of enqueue.
int item = await buffer.ReceiveAsync(); // instead of dequeue.