1

なぜ今日受け取ったのか理解できませんSystem.IndexOutOfRangeException。プログラムがすでに 8 時間動作していて、例外が発生した場所が何百万回も実行されたときに、それを受け取りました。この場所は非常に単純です。

for (int i = 0; i < _goldDesiredOrdersBuy.Length; i++)
{
    _goldDesiredOrdersBuy[i] = -1;               // IndexOutOfRangeException! Strategy3.cs:line 666
}

プログラムの開始時に _goldDesiredOrdersBuy を 1 回だけ初期化するので、例外が発生したときに初期化されることが保証されます。

private int[] _goldDesiredOrdersBuy = new int[MaxOrderbookDepth];

この配列に触れる場所がもう 1 つあります。

    private int GetGoldVolumeBuy(int bidQuotesPos)
    {
        if (_goldDesiredOrdersBuy[bidQuotesPos] > -1)
        {
            return _goldDesiredOrdersBuy[bidQuotesPos];
        }
        int result = GetGoldVolumeBuyNotCached(bidQuotesPos);
        _goldDesiredOrdersBuy[bidQuotesPos] = result;
        return result;
    }

それだけです。_goldDesiredOrdersBuyアプリケーションの起動時に一度初期化され、初期化されることが保証され、配列の長さがどこにも変更されていないため、どのように受け取ったのかわかりませんIndexOutOfRangeException。何か考えはありますか?

Unhandled Exception: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. --->
   System.AggregateException: One or more errors occurred. --->
   System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at MyProj.Strategies.Strategy3.CalculateNewDesiredOrdersBuy() in C:\Oleg\projects\MyProj\MyProj\Strategies\Strategy3.cs:line 666
   at MyProj.Strategies.Strategy3.RecalculateBuyOrders() in C:\Oleg\projects\MyProj\MyProj\Strategies\Strategy3.cs:line 567
   at MyProj.Strategies.Strategy3.OnAllTablesUpdated() in C:\Oleg\projects\MyProj\MyProj\Strategies\Strategy3.cs:line 499
   at MyProj.Strategies.Strategy3.AllTablesUpdated() in C:\Oleg\projects\MyProj\MyProj\Strategies\Strategy3.cs:line 413
   at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()
   at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
   at System.Threading.Tasks.Task.<>c__DisplayClass7.<ExecuteSelfReplicating>b__6(Object )
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at System.Threading.Tasks.Parallel.ForWorker[TLocal](Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
   at MyProj.Market.FinishUpdatingTables() in C:\Oleg\projects\MyProj\MyProj\Market.cs:line 449
   at Library.Exchange.Gate.DoGateIteration() in C:\Oleg\projects\MyProj\MyProj\Gate.cs:line 143
   at Library.Exchange.Gate.<Connect>b__0() in C:\Oleg\projects\MyProj\MyProj\Gate.cs:line 98
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.TaskExceptionHolder.Finalize()
4

4 に答える 4

2

MSDNからSystem.Array

インスタンス メンバーは、スレッド セーフであるとは限りません。

この配列インスタンスを複数のスレッドで共有すると、ドキュメントに反することになります。きちんとロックする必要があります。

于 2012-07-02T18:21:16.307 に答える
1

Imoint index問題は、 (またはそのようなもの) のようなパラメーターを受け入れ、そのパラメーターを使用して配列からデータを回復する関数がいくつかあることです。

配列のサイズは変更されていません。問題ありません。ただし、配列の長さが静的で (たとえば) 5 に等しい場合でも、 でその配列にアクセスしようとするとindex>=5、説明した例外が発生します。

編集

ループ内で例外が発生し、そのfor(...)境界が配列自体のサイズでマークされていることを考慮すると、別の可能性があります。実行スタックを考慮すると、ものを並列に実行すると言えます。したがって、この時点で、配列のサイズが何らかの形で変化すると思います。

これを確認するには、次のことを試してください。

int limit = _goldDesiredOrdersBuy.Length; //SET LIMIT BEFORE ITERATION
for (int i = 0; i < limit ; i++)
{
    _goldDesiredOrdersBuy[i] = -1;           
}

それでもエラーが発生するかどうかを確認します。

お役に立てれば。

于 2012-07-02T17:58:13.217 に答える
0

このメソッドは、渡された有効なインデックスをチェックしません。
そのため、ここでいくつかの安全チェックを行います。

private int GetGoldVolumeBuy(int bidQuotesPos) 
{ 
    int result = -1;
    if(bidQuotesPos >= 0 && bidQuotesPos < _goldDesiredOrdersBuy.Length)
    {
        if (_goldDesiredOrdersBuy[bidQuotesPos] > -1) 
        { 
            return _goldDesiredOrdersBuy[bidQuotesPos]; 
        } 
        result = GetGoldVolumeBuyNotCached(bidQuotesPos); 
        _goldDesiredOrdersBuy[bidQuotesPos] = result; 
    }
    return result; 
} 

result=-1ここで有効な出力であると想定しています

于 2012-07-02T17:58:05.770 に答える
0

bidQuotesPosの値が配列の範囲内にあることを確認していません。

private int GetGoldVolumeBuy(int bidQuotesPos) 
{ 
    if (bidQuotesPos < 0 || bidQuotesPos >= _goldDesiredOrdersBuy.Length)
    {
        // either throw an exception, or (less desireable) return a value so that the caller
        // knows that an error occurred.
        return HandleInvalidInputValue(bidQuotesPos);
    }

    if (_goldDesiredOrdersBuy[bidQuotesPos] > -1) 
    { 
        return _goldDesiredOrdersBuy[bidQuotesPos]; 
    } 
    int result = GetGoldVolumeBuyNotCached(bidQuotesPos); 
    _goldDesiredOrdersBuy[bidQuotesPos] = result; 
    return result; 
} 
于 2012-07-02T17:58:45.167 に答える