c# - 处理来自套接字流的数据时,集合被修改错误
问题描述
我正在尝试从 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 对象,这就是您看到集合修改异常的原因。
我建议您重新考虑代码设计,以免多个线程处理相同的对象。如果您绝对必须让线程处理相同的对象,那么应该使用 lock:
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# 中的锁和多线程。
推荐阅读
- python - 获取networkx图python中邻居节点的属性
- node.js - ENOENT:运行 npm install 命令时没有这样的文件或目录
- google-colaboratory - 如何对 Google Colab 上的某行发表评论?
- html - 元素内的垂直居中图像
- angular - ng serve --port 4200 和 ng serve --host ip:4200 的区别
- jpa - JPA中实体的替代初始值
- flutter - 流式传输数据时如何通过小部件构建条件?
- python - pandas 使用外部列表计算值
- mysql - 这是3NF吗?
- android - 无法从下载目录中获取任何文件