Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使使用队列线程的异步方法安全_C#_.net_Thread Safety_Async Await - Fatal编程技术网

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)?@user4287276
ConcurrentQueue
确保对其方法之一的每次调用本身是线程安全的。这不是一个锁定机制。如果您的代码需要同步,您应该使用
(或者
异步锁
,如果合适的话)。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.