0
我正在编写一个外汇交易机器人,并且在使用BlockingCollection一段时间后(约2小时)运行outOfMemory异常。 我基本1个队列对贸易图表,被加入到一个字典:c#BlockingCollection导致内存不足
private Dictionary<string, BlockingCollection<tick>> tickQueues = new Dictionary<string, BlockingCollection<tick>>();
我检查存储器转储一小时后,我可以看到以下项目堆放:
Count Size(bytes) Inclusive Size
ThreadPoolWorkQueue+QueueSegment 22,951 24,236,256 40,316,868
QueueUserWorkItemCallback 689,838 13,796,760 16,081,272
TimerQueueTimer 11,160 713,772 2,355,736
我有一个计时器,它负责将数据添加到队列:
private void TickTimer_tick(object source, ElapsedEventArgs e) {
if (Monitor.TryEnter(LockTimerTick, GlobalSettings.APISleepDelayMSTick)) {
updateLockFailCount = 0;
try {
tick t = new tick(DateTime.Now, d.bid, d.ask);
lastBid = d.bid;
lastAsk = d.ask;
t.pair = Inst.pair;
//myTickQueue.TryAdd(t);
if (!myTickQueue.TryAdd(t)) {
functions.Logger.log("Error when adding Tick on Queue for " + Inst.pair+ " Maybe Queue is full", "SHMAPI", LOGLEVEL.WARN);
}
} catch (Exception E) {
functions.Logger.log("Error happened when refreshing tick data: " + E.Message, "SHMAPI", LOGLEVEL.ERROR);
} finally {
Monitor.Exit(LockTimerTick);
}
} else {
updateLockFailCount++;
int sev = LOGLEVEL.TRACE;
if (updateLockFailCount == 10) { sev = LOGLEVEL.DEBUG; }
if (updateLockFailCount==50) { sev = LOGLEVEL.WARN; }
if (updateLockFailCount % 100 == 0 && updateLockFailCount>=100) { sev = LOGLEVEL.ERROR; }
functions.Logger.log("Could not get lock to refresh tick data for symbol "+Symbol, "SHMAPI", sev);
}
}
最后,我的任务,检查问:
public void startQueueTask(string Pair) {
if (!tickQueues.ContainsKey(Pair.ToUpper())) {
tickQueues.Add(Pair.ToUpper(), new BlockingCollection<tick>(GlobalSettings.tickQueueSize));
if (!MTAPIs.ContainsKey(Pair.ToUpper())) {
throw new Exception("API for pair " + Pair + " Should be initialized !!");
}
MTAPIs[Pair.ToUpper()].setTickQueue(tickQueues[Pair.ToUpper()]);
functions.Logger.log("Starting " + Pair + " Queue Task", "TICKPROCESSING", LOGLEVEL.DEBUG);
Task.Run(() => {
foreach (tick tick in tickQueues[Pair.ToUpper()].GetConsumingEnumerable()) {
try {
onTick(tick);
} catch (Exception E) {
functions.Logger.log("Error processing tick for symbol " + tick.pair + " " + E.Message, "TICKPROCESSING", LOGLEVEL.ERROR);
functions.printException(E);
}
}
functions.Logger.log("Exiting Queue Task", "TICKPROCESSING", LOGLEVEL.ERROR);
});
} else {
functions.Logger.log("Skipping " + Pair + " Queue Task because already exists", "TICKPROCESSING", LOGLEVEL.DEBUG);
}
}
我真的不知道为什么我收到OOM,但它看起来类似于: http://blogs.microsoft.co.il/bnaya/2012/02/26/real-life-story-blocking-collection/ 但我不是在这里使用并行...我的队列为空,虽然本周以来高端市场被关闭。 与TryDequeue一起使用另一个计时器会有更好的方法吗? 任何建议将受到欢迎!
它看起来像你正在使用System.Timers.Timer?如果是这样,那么间隔是多少?计时器标记方法需要多长时间?定时器上AutoReset的值是多少? –
我没有看到明显的问题,但我没有听说您发布的链接问题。但是...如果它是相似的,尝试使用TaskFactory.StartNew启动任务,并将TaskCreationOptions设置为LongRunning 另外:1)您的命名约定很糟糕,您无法看到与类,局部变量,方法不同的...尝试将其更改为更多的C#,如:P 2)摆脱ToUpper()通过设置额外的构造函数参数给StringComparer.InvariantCultureIgnoreCase :)它将更干净,更快 – Carnifex
嘿,我有计时器每隔50ms启动.. 。我实际上认为我的问题可能是由于计时器事件堆积而造成的......我会尝试手动重置并让您知道。仅供参考,定时器定义: TickTimer = new System.Timers.Timer(); TickTimer.Elapsed + = new ElapsedEventHandler(TickTimer_tick); TickTimer.Interval = GlobalSettings.APISleepDelayMSTick; // 50 MS TickTimer.AutoReset = true; //让计时器触发重复事件(true为默认值) TickTimer.Enabled = true; – bmigette