upd 我发现AutoResetEvent按预期工作。似乎我在CalculateAndNotify
内的某个地方有异常。所以这个问题不再是关于AutoResetEvent了。但是,如果您可以建议如何更好地计算HFT软件中的索引 - 欢迎提出意见。
=============================================== ===============================
我在下面添加了我班级的完整列表。有两个重要的方法。 Calculate
每次调用InstrumentUpdated
时都会重新计算索引值。
class CompositeIndex : CustomIndex
{
//private Tuple<Instrument, double>[] _instrumentsWithWeight;
//private int[] _instrumentIds;
//private double[] _ammounts;
//private double[] _cachedProduct; // one thread writes here and another thread reads. so need to use "Volatile"
//private volatile bool _initialized;
//AutoResetEvent are = new AutoResetEvent(false);
//public CompositeIndex(string indexId, Tuple<Instrument, double>[] instrumentsWithWeight)
// : base(indexId, GetInstruments(instrumentsWithWeight))
//{
// _instrumentsWithWeight = instrumentsWithWeight;
// _instrumentIds = new int[_instrumentsWithWeight.Count()];
// _ammounts = new double[Commons.Constants.MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];
// _cachedProduct = new double[Commons.Constants.MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];
Task.Factory.StartNew(() =>
{
while(true)
{
if (_initialized)
{
break;
}
Thread.Sleep(1000);
}
while (true)
{
are.WaitOne(); // hangs here!
CalculateAndNotify();
}
}
, TaskCreationOptions.LongRunning);
}
//private static List<Instrument> GetInstruments(Tuple<Instrument, double>[] instrumentsWithWeight)
//{
// List<Instrument> result = new List<Instrument>();
// for (int i = 0; i < instrumentsWithWeight.Count(); i++)
// {
// result.Add(instrumentsWithWeight[i].Item1);
// }
// return result;
//}
//protected override void Calculate()
//{
// double result = 0;
// for (int i = 0; i < _instrumentIds.Count(); i++)
// {
// int instrumentId = _instrumentIds[i];
// // we assign 0 weself so this comparision is OK
// double cachedProduct = Volatile.Read(ref _cachedProduct[instrumentId]);
// if (cachedProduct == 0)
// {
// Value = null;
// return;
// }
// result += cachedProduct;
// }
// Value = result;
//}
//private object _initializeLock = new object();
//private bool Initialize()
//{
// lock (_initializeLock)
// {
// if (_initialized)
// {
// return true;
// }
// for (int i = 0; i < _instrumentsWithWeight.Count(); i++)
// {
// Instrument instrument = _instrumentsWithWeight[i].Item1;
// double weight = _instrumentsWithWeight[i].Item2;
// _instrumentIds[i] = instrument.Id;
// _ammounts[instrument.Id] = weight;
// }
// _initialized = true;
// return true;
// }
//}
public override void InstrumentUpdated(Instrument instrument)
{
//if (!_initialized)
//{
// if (!Initialize())
// {
// return;
// }
//}
//int instrumentId = instrument.Id;
//bool useSecurityInsteadOfOrderBook = instrument.GateId == 1;
//decimal? value;
//if (useSecurityInsteadOfOrderBook)
//{
// InstrumentInfo ii = Markets.GetInstrumentInfo(instrument);
// value = ii.MedianOrAskOrBid;
//} else
//{
// Glass glass = Markets.GetGlass(instrument);
// value = glass.MedianOrAskOrBid;
//}
//if (value == null)
//{
// Volatile.Write(ref _cachedProduct[instrumentId], 0);
//}
//else
//{
// Volatile.Write(ref _cachedProduct[instrumentId], ((double)value) * _ammounts[instrumentId]);
//}
are.Set(); // called many times!
}
}
我添加了一些跟踪并注意到:
一个帖子挂起are.WaitOne()
。尽管另一个线程多次调用are.Set()
,但第一个线程未被释放。
为什么?我的代码出了什么问题?
答案 0 :(得分:0)
public override void InstrumentUpdated(Instrument instrument)
{
//your code
// are.Set - do not need
Task.Factory.StartNew(CalculateAndNotify, TaskCreationOptions.LongRunning);
}
您应该更改CalculateAndNotify
protected void CalculateAndNotify()
{
if (Monitor.TryEnter(someObject))
{
try
{
// your code
}
finally
{
Monitor.Exit(someObject);
}
}
}
可能会做你想做的事情