AutoResetEvent由于某种原因不起作用

时间:2012-11-02 07:48:49

标签: c# multithreading events autoresetevent

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(),但第一个线程未被释放。 为什么?我的代码出了什么问题?

1 个答案:

答案 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);
         }
     }
 }

可能会做你想做的事情