gpt4 book ai didi

c# - 多个线程访问一个集合

转载 作者:行者123 更新时间:2023-11-30 21:41:37 25 4
gpt4 key购买 nike

我有以下场景。

我有一个接收消息的队列。当一条消息传入时,将创建一个新线程来处理它。

此线程获取消息并将其添加到集合中。然后检查集合是否包含 100 个项目,如果包含,则将它们发送到其他地方并清除集合。

我不能使用常规列表,因为我得到集合被修改,枚举不能继续的错误。所以我需要使用线程安全的集合。

但我担心的是,一个线程写入它和它的第 100 个项目,同时将它们发送到其他地方,另一个线程添加到集合中。使其成为 101 个项目,触发第 100 个的线程然后将其清除,我丢失了一个项目。

我不能使用并发包,因为它没有清除,我不能迭代包并逐一删除,因为消息可能传入和添加的速度快于它可以删除的速度,而且它永远不会结束。

ConcurrentStack 很清楚,但在这种情况下行得通吗?

一些代码可以证明我的意思,HandleMeasurementMessage 发生在每条消息的新线程上。

private static readonly ConcurrentStack<EventHubDatum> EventHubDataBatch = new ConcurrentStack<EventHubDatum>();

private static void HandleMeasurementMessage(IMessage<MessageEnvelope> msg)
{
/* Do a bunch of stuff to msg */

EventHubDataBatch.Push(eventHubDatum);

if(EventHubDataBatch.Count == 100)
{
/* Send them off*/
EventHubDatabatch.Clear();
}
}

奇怪的是,只有当我没有通过 VS2015 中的调试器运行枚举时,才会出现修改枚举的问题。程序运行一个小时左右就好了。如果我关闭调试器,我会收到这些枚举错误,这就是我尝试切换到线程安全集合的原因。我只是不确定哪个合适。

调用HandleMeasurementMessage的代码

_busSingle.Consume<MessageEnvelope>(_queueMeasurement, (msg, MessageReceivedInfo) => Task.Factory.StartNew(() =>
{
try
{
HandleMeasurementMessage(msg);
}
catch (Exception ex)
{
/* Logging stuff*/
}
}));

最佳答案

我会像这样使用简单的锁:

private static readonly List<EventHubDatum> EventHubDataBatch = new List<EventHubDatum>();        
private static void HandleMeasurementMessage(IMessage<MessageEnvelope> msg)
{
/* Do a bunch of stuff to msg */

EventHubDatum[] toSend = null;
lock (EventHubDataBatch) {
EventHubDataBatch.Add(eventHubDatum);

if (EventHubDataBatch.Count == 100) {
// copy to local
toSend = EventHubDataBatch.ToArray();
EventHubDataBatch.Clear();
}
}

if (toSend != null) {
/* Send them off*/
}
}

此处的锁定非常简短,因此它不会以任何明显的方式影响您案例的性能。请注意,如果有 100 个项目 - 我们将它们复制到本地数组并清除源列表以在“发送它们”操作期间不持有锁,这可能会花费很长时间。

关于c# - 多个线程访问一个集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43116966/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com