2012-10-30 17 views
6

Ich bin eine PLINQ-Abfrage läuft wie folgt:PLINQ-Abfrage geben Überlaufausnahme

ParallelQuery<string> winningCombos = from n in nextComboMaker.GetNextCombo() 
               .AsParallel().WithCancellation(_cancelSource.Token) 
               where ComboWasAWinner(n) 
               select n; 

ConcurrentBag<string> wins = new ConcurrentBag<string>(); 

foreach (var winningCombo in winningCombos) 
{ 
     wins.Add(winningCombo); 
     if (wins.Count == _maxWinsAllowed) 
      break; 
} 

Die GetNextCombo Methode nur, um die nächste Kombination aus Buchstaben und Zahlen zurückkehren, mit Möglichkeiten zu den Milliarden/Billionen auf.

Nun ist diese wirft die Ausnahme, wenn ich eine Reihe von Kombinationen größer als die zulässige Größe eines Int32 wählen, wirft es immer, wenn der Zähler von Combos es laufen gelassen ist 2147483584.

ich sicher, dass ich gemacht es ist nichts in der GetNextCombo durch eine gefälschte Combo zu schaffen jedes Mal (dabei eine yield return "234gf24fa23 ..." etc.) zurückzukehren

die Ausnahme von LINQ geworfen wird:

System.AggregateException was unhandled by user code 
    Message=One or more errors occurred. 
    Source=System.Core 
    StackTrace: 
     at System.Linq.Parallel.QueryTaskGroupState.QueryEnd(Boolean userInitiatedDispose) 
     at System.Linq.Parallel.MergeExecutor`1.Execute[TKey](PartitionedStream`2 partitions, Boolean ignoreOutput, ParallelMergeOptions options, TaskScheduler taskScheduler, Boolean isOrdered, CancellationState cancellationState, Int32 queryId) 
     at System.Linq.Parallel.PartitionedStreamMerger`1.Receive[TKey](PartitionedStream`2 partitionedStream) 
     at System.Linq.Parallel.ForAllOperator`1.WrapPartitionedStream[TKey](PartitionedStream`2 inputStream, IPartitionedStreamRecipient`1 recipient, Boolean preferStriping, QuerySettings settings) 
     at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.ChildResultsRecipient.Receive[TKey](PartitionedStream`2 inputStream) 
     at System.Linq.Parallel.WhereQueryOperator`1.WrapPartitionedStream[TKey](PartitionedStream`2 inputStream, IPartitionedStreamRecipient`1 recipient, Boolean preferStriping, QuerySettings settings) 
     at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.ChildResultsRecipient.Receive[TKey](PartitionedStream`2 inputStream) 
     at System.Linq.Parallel.ScanQueryOperator`1.ScanEnumerableQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient) 
     at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient) 
     at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient) 
     at System.Linq.Parallel.QueryOperator`1.GetOpenedEnumerator(Nullable`1 mergeOptions, Boolean suppressOrder, Boolean forEffect, QuerySettings querySettings) 
     at System.Linq.Parallel.ForAllOperator`1.RunSynchronously() 
     at StockWiz.Library.PLINQArrayProcessor.DoProcessing() in C:\Users\dad\Documents\BitBucket\stockwiz_clone\stockwiz\StockWiz.Library\PLINQArrayProcessor.cs:line 50 
     at System.Threading.Tasks.Task.Execute() 
    InnerException: System.OverflowException 
     Message=Arithmetic operation resulted in an overflow. 
     Source=System.Core 
     StackTrace: 
      at System.Linq.Parallel.PartitionedDataSource`1.ContiguousChunkLazyEnumerator.MoveNext(T& currentElement, Int32& currentKey) 
      at System.Linq.Parallel.WhereQueryOperator`1.WhereQueryOperatorEnumerator`1.MoveNext(TInputOutput& currentElement, TKey& currentKey) 
      at System.Linq.Parallel.ForAllOperator`1.ForAllEnumerator`1.MoveNext(TInput& currentElement, Int32& currentKey) 
      at System.Linq.Parallel.ForAllSpoolingTask`2.SpoolingWork() 
      at System.Linq.Parallel.SpoolingTaskBase.Work() 
      at System.Linq.Parallel.QueryTask.BaseWork(Object unused) 
      at System.Threading.Tasks.Task.Execute() 
     InnerException: 

ich mich, wenn Es gibt etwas, was ich tun kann, um dieses Quer zu ändern y nicht Überlauf, jede Reihenfolge, in der ich die Dinge tun, usw. Vielleicht hat nicht die Linq-Abfrage ein, wo zu tun und wählen, obwohl ich das versucht habe:

var query = nextComboMaker.GetNextCombo().AsParallel(); 

query.ForAll(x => if(ComboWasAWinner(x) wins.Add(x)); 

immer noch den gleichen Überlauf.

Antwort

6

Sie sollten in der Lage sein, dies zu umgehen, indem Sie einen benutzerdefinierten Partitionierer verwenden. Der von PLINQ ausgewählte Standard-Partitionierer unterstützt in diesem Fall nur eine int-Bereichsanzahl von Elementen.

Siehe http://msdn.microsoft.com/en-us/library/dd997416.aspx für wie dies zu tun ist.

+0

wird nicht für mich arbeiten, müssen Sie tun. ToArray oder ToList() auf der IEnumerable Ich bin parallel über und das wird einen Stapelüberlauf erstellen, sobald die Größe größer als ein int ist. Was genau kann ich außer Kraft setzen, damit es lange zählt? –