upd: Let me rephrase my question shortly.
There are N double numbers. There are N dedicated threads each of them update own double number (_cachedProduct
in the example below).
Somehow I need to have sum
of these numbers and I need IndexUpdated
event to be raised ASAP after any double number is changed (it would be nice if such event can be raised in 10 µs or less).
Below is how I tried to implement this task
===============================================
To calculate stock exchange index I create private double[] _cachedProduct;
field. These field is written
by many threads
// called from another threads
public override void InstrumentUpdated(Instrument instrument)
{
if (!_initialized)
{
if (!Initialize())
{
return;
}
}
int instrumentId = instrument.Id;
OrderBook ob = Program.market.OrderBook(instrument);
if (ob.MedianOrAskOrBid == null)
{
_cachedProduct[instrumentId] = 0;
}
else
{
_cachedProduct[instrumentId] = ((double) ob.MedianOrAskOrBid)*_ammounts[instrumentId];
}
}
_ammounts
is pre-initialized array and please ignore Initialize
method and variable - they just works.
In loop I just sum all _cachedProduct and when values changes I notify others.
Task.Factory.StartNew(() =>
{
while(true)
{
if (_initialized)
{
break;
}
}
while (true)
{
CalculateAndNotify();
//Thread.Sleep(5);
}
}
, TaskCreationOptions.LongRunning);
protected void CalculateAndNotify()
{
var oldValue = Value;
Calculate();
if (oldValue != Value)
{
NotifyIndexChanged();
}
}
protected override void Calculate()
{
double result = 0;
for (int i = 0; i < _instrumentIds.Count(); i++)
{
int instrumentId = _instrumentIds[i];
if (_cachedProduct[instrumentId] == 0)
{
Value = null;
return;
}
result += _cachedProduct[instrumentId];;
}
Value = result;
}
I must use Interlocked
to update my double _cachedProduct
values but please ignore that fact now, what other problems with this code do you see?
Should I call Calculate
method inside while(true)
so I always
use one core without delays. My machine has 24 cores so I was thinking this is ok.
However without Thread.Sleep(5)
(commented) I do see significant slow-down in the program overall and I do not understand why. Program executes several dozens times slower in many places.
The question is if my idea of using while(true)
without any locking at all is OK. Or should I introduce some locking method so I would only Calculate
index when one of of _cachedProduct
is updated?