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()
多次调用第一个线程并没有被释放。为什么?我的代码有什么问题?