如何解决处理来自套接字流的数据时集合被修改错误
我正在尝试从 Binance 聚合数据流中捕获刻度级别数据。一旦日期发生变化,函数就会处理前一天的数据。我正在使用 Task.Run 创建另一个线程,因为当天的新数据仍在流入并需要捕获。但是,我收到“集合已修改,枚举操作可能无法执行”的消息。在处理数据的函数的 foreach 循环中。我不确定为什么在传递给处理函数后会修改 TradeData?不确定这是否重要,但我在不同的线程上捕获了大约 40 个不同的符号。
private static void Start()
{
foreach (SymbolData symbol in symbolData)
{
Task.Run(() => SubscribetoSymbol(symbol.symbol));
}
}
private static void SubscribetoSymbol(string symbol)
{
Dictionary<decimal,decimal> TradeData = new Dictionary<decimal,decimal>();
DateTime lastTrade = DateTime.UtcNow;
try
{
var socketClient = new BinanceSocketClient();
socketClient.FuturesUsdt.SubscribetoAggregatedTradeUpdates(symbol,data =>
{
if (data.TradeTime.Date > lastTrade.Date)
{
Task.Run(() => ProcessData(symbol,lastTrade.Date,TradeData));
TradeData.Clear();
}
lastTrade = data.TradeTime;
if (TradeData.ContainsKey(data.Price))
{
TradeData[data.Price] = TradeData[data.Price] + data.Quantity;
}
else
{
TradeData[data.Price] = data.Quantity;
}
});
}
catch { }
}
private static void ProcessData(string symbol,DateTime date,Dictionary<decimal,decimal> TradeData)
{
foreach (var price in TradeData)
{
//Error: Collection was modified enumeration operation may not execute.
}
}
解决方法
您重复调用 Task.Run,结果有多个线程处理您的 tradeData 对象,这就是您看到集合修改异常的原因。
我建议您重新考虑代码设计,以免多个线程处理相同的对象。如果您绝对必须让线程处理相同的对象,则应使用锁:
private static object _objlock = new object();
private static void ProcessData(string symbol,DateTime date,Dictionary<decimal,decimal> tradeData)
{
lock (_objlock)
{
foreach (var price in tradeData)
{
}
}
}
使用锁时要小心死锁。我建议阅读 C# 中的锁和多线程。
,当您在字典上开始 foreach 循环时,外部正在“清除”它。
您应该复印一份并发送给ProcessData
。
Task.Run(() => ProcessData(symbol,lastTrade.Date,tradeData.ToArray()));
并接收副本:
private static void ProcessData(string symbol,KeyValuePair<decimal,decimal>[] tradeData)
{
foreach (var price in tradeData)
{
// ... do your thing here
}
}
或者,更简单的方法是重新创建一个新字典而不是清除它:
//tradeData.Clear();
tradeData = new Dictionary<decimal,decimal>();
,
有一次我在 foreach 循环中从列表中删除值时遇到类似问题,我已将其更改为简单的 for 循环,这有助于您尝试。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。