[英]Proper use of .NET Concurrent Collections
In my attempt to create concurrent Socket
operations, I've created the following code: 在我尝试创建并发
Socket
操作时,我创建了以下代码:
ConcurrentQueue<byte[]> messageQueue;
ManualResetEvent resetEvent;
Thread outThread; // -> new Thread(BeginSending);
public void BeginSending() // invoked by outThread
{
while (true)
{
resetEvent.WaitOne();
while (messageQueue.Count > 0)
{
byte[] msg;
messageQueue.TryDequeue(out msg);
// send msg via socket
}
resetEvent.Reset();
}
}
public void QueueMessage(byte[] msg) // invoked by the main thread
{
messageQueue.Enqueue(msg);
resetEvent.Set();
}
Is adding items to the ConcurrentQueue
while a different thread is iterating/dequeuing it a dangerous thing? 将项目添加到
ConcurrentQueue
而另一个线程迭代/出列是危险的事情?
From my understanding many synchronized collections simply have individually synchronized methods, but is the same true for concurrentQueue
and similar collections? 根据我的理解,许多同步集合只是单独同步的方法,但对于
concurrentQueue
和类似的集合是一样的吗?
( ConcurrentBag
, ConcurrentDictionary
, ConcurrentStack
) (
ConcurrentBag
, ConcurrentDictionary
, ConcurrentStack
)
The ConcurrentQueue
itself is OK, as long as you are not mutating the arrays stored as its elements. ConcurrentQueue
本身没问题,只要你没有改变存储为其元素的数组。
However, your usage pattern with ManualResetEvent
suggests that there is a better solution: if you use BlockingCollection<T>
, you would be able to avoid doing manual synchronization. 但是,使用
ManualResetEvent
的使用模式表明有更好的解决方案:如果使用BlockingCollection<T>
,则可以避免进行手动同步。
Is adding items to the ConcurrentQueue while a different thread is iterating/dequeuing it a dangerous thing?
将项目添加到ConcurrentQueue,而另一个线程迭代/出列是危险的事情?
No, it is safe. 不,这很安全。
The ConcurrentQueue is fine, the ManualResetEvent is not: ConcurrentQueue很好,ManualResetEvent不是:
public void BeginSending() // invoked by outThread
{
while (true)
{
resetEvent.WaitOne();
while (messageQueue.Count > 0)
{
byte[] msg;
messageQueue.TryDequeue(out msg);
// send msg via socket
}
// context change
messageQueue.Enqueue(msg);
resetEvent.Set();
// context change
resetEvent.Reset();
}
}
Such a sequence of events will result in an enqueued message being ignored. 这样的事件序列将导致忽略排队的消息。 Either use a BlockingCollection, as suggested by the other posters, or use a semaphore for signal/wait.
要么使用其他海报建议的BlockingCollection,要么使用信号量进行信号/等待。
The concurrent collections are designed to be thread safe. 并发集合设计为线程安全的。 Using them saves you a lot of trouble by implementing them yourself.
使用它们可以自己实现它们,从而为您节省很多麻烦。
Be aware though that the collection itself is synchronized, NOT the data inside it. 请注意,集合本身是同步的,而不是其中的数据。 Updating the objects inside the collections without attention for the other threads can bring race-conditions.
更新集合中的对象而不关注其他线程可能会带来竞争条件。
As with any usage of a class it helps if you have a understanding of the use and use-cases of the collections 与任何类的使用一样,如果您了解集合的用法和用例,它会有所帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.