upd:私の質問を簡単に言い換えさせてください。N 個の二重数があります。N 個の専用スレッドがあり、それぞれが独自の倍精度数を更新します (_cachedProduct
以下の例)。
どういうわけかsum
、これらの数値を取得する必要がありIndexUpdated
、2 倍の数値が変更された後、できるだけ早くイベントを発生させる必要があります (そのようなイベントを 10 μs 以下で発生させることができればよいでしょう)。
以下は、このタスクを実装しようとした方法です
===============================================
証券取引所指数を計算するには、private double[] _cachedProduct;
フィールドを作成します。これらのフィールドは多くのスレッドによって書き込まれます
// 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
は事前に初期化された配列であり、Initialize
メソッドと変数を無視してください - それらは機能します。
ループでは、すべての _cachedProduct を合計し、値が変更されたときに他の人に通知します。
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;
}
Interlocked
double 値を更新するために使用する必要があり_cachedProduct
ますが、今はその事実を無視してください。このコードには他にどのような問題がありますか?
Calculate
内部でメソッドを呼び出す必要がwhile(true)
あるので、always
遅延なく 1 つのコアを使用します。私のマシンには24コアがあるので、これでいいと思っていました。
ただし、Thread.Sleep(5)
(コメントなしで)プログラム全体で大幅な速度低下が見られますが、その理由はわかりません。プログラムは、多くの場所で数十倍遅く実行されます。
while(true)
問題は、ロックをまったく使用せずに使用するという私の考えが正しいかどうかです。または、ロック方法を導入して、いずれかが更新されCalculate
たときにのみインデックスを作成する必要がありますか?_cachedProduct