C# 使用多线程应用程序执行自动重置事件
我开发了一个基于股票交易的金融服务应用程序。应用程序背后的思想是对多个符号/票据执行各种计算,并同时为每个符号生成买入和卖出信号。每秒从数据供应商处接收数据,然后执行计算 背景: 为此,我创建了一个Calculations类,它将接收单个符号的数据,执行计算并生成买入/卖出信号 为了对多个符号执行计算,我将在单独的线程中为每个符号实例化calculations对象,如下所示C# 使用多线程应用程序执行自动重置事件,c#,multithreading,performance,trading,C#,Multithreading,Performance,Trading,我开发了一个基于股票交易的金融服务应用程序。应用程序背后的思想是对多个符号/票据执行各种计算,并同时为每个符号生成买入和卖出信号。每秒从数据供应商处接收数据,然后执行计算 背景: 为此,我创建了一个Calculations类,它将接收单个符号的数据,执行计算并生成买入/卖出信号 为了对多个符号执行计算,我将在单独的线程中为每个符号实例化calculations对象,如下所示 EventWaitHandle ew = new AutoResetEvent(initialState: fal
EventWaitHandle ew = new AutoResetEvent(initialState: false);
Thread t = new Thread(() => RunCalculations(s));
_waitList.Add(s.Symbol, ew);
t.Name = s.Symbol;
t.Start();
threadList.Add(s.Symbol, t);
上述代码在每个符号上通过foreach进行迭代。
这就是在RunCalculations()时发生的情况代码>
calc.AddTickItem()
将只发送属于线程的一个符号的数据值。在calc
对象的Addtickitem
方法中调用进一步的计算
通过AutoResetEvent,Iam在另一个方法中添加了一个数据项,该方法调用\u waitList[data.Symbol].Set()代码>在每个线程上
问题
计算很顺利。但问题在于添加更多线程(或符号)时的性能。我们测试了极限,发现它只能在18-20个符号左右正常工作。若我们增加更多,那个么计算部分将在市场时间结束前半小时延迟。但在那之前,它工作得很好。另一个关键点是,这种情况并非每天都发生。我们已经测试了多达28个符号,并将其恢复到19个,目前其工作稳定
据我所知,由于Iam使用事件信号,它不应该对CPU资源更密集。CPU实际上是一个2核intel i3处理器
但我仍然想知道,这是处理器的问题还是应该改变应用程序的体系结构?我曾想过改变线程管理的体系结构,不再使用符号,而是将每个计算部分放在不同的线程中。但问题是,存在一些依赖计算,其中存在邪恶的并发同步;)让我做噩梦
我会更换处理器,但我必须知道什么是最佳处理器(4核、8核等)。据我所知,只有内核并不能解决问题
如有任何建议,将不胜感激
谢谢。这是一个非常错误的代码,如果事件被发送两次信号,它将严重失败。你添加的符号越多,就越有可能出现这种情况。无法使用AutoResetEvent实现正确的生产者-消费者。谷歌“.net生产者消费者队列”的基本点击。我建议改变整个方法,并利用消息和队列。您可以根据扩展能力、冗余度等设置不同的端点。请看一下使用类似ESB的穿梭机:@HansPassant Yeah。。。我已经考虑过了。。。但是我已经为每个线程分离了自动resetEvents。因此,每个线程都有自己的AutoResetEvent。这将最大限度地减少发出两次信号的机会。我收到的数据对单个符号的周期差最小为1秒,最大约为2分钟。这是单个生产者和多个消费者的情况。但我明白你的意思。。。。谢谢…@Neilvereynne,但就我而言,我不能建立队列,希望在以后的阶段计算数据点。反应时间应尽可能短。即使有2或3个数据点在队列中等待稍后的计算,这也没有帮助,相反,我可以跳过这些数据点,然后取下一个数据点。我可以跳过,但不会太多…如果没有,就不可能评估任何可能导致性能问题的因素。它可能与AutoResetEvent
的使用有关,也可能与之无关。也就是说,ARE
使用本机Windows事件,在这种情况下,这些事件不如Monitor
类,甚至可能不如其他.NET同步对象之一有效。所以你可以试着换一种。
private void RunCalculations(Symbols symbol)
{
Calculations calc = new Calculations(symbol);
while (true)
{
_waitList[symbol.Symbol].WaitOne();
if(!keepRunning[symbol.Symbol])
{
calc.Stop();
return;
}
MarketData d = null;
if(_mktDataQueue.TryDequeue(out d))
{
if (calc.SymbolName == d.Symbol)
calc.AddTickItem(d);
}
}
}