Wie kann BlockingCollection (T) .GetConsumingEnumerable () OperationCanceledException auslösen?

8

Ich verwende eine BlockingCollection, um einen Taskplaner zu implementieren, im Grunde:

%Vor%

Ich habe das nur einmal gesehen und konnte das nicht reproduzieren, aber irgendwann auf der foreach (in TryTakeWithNoTimeValidation ) Ich habe eine OperationCanceledException erhalten. Ich verstehe nicht, da ich die Überladung verwende, die kein CancellationToken und die Dokumentation enthält , dass es nur eine ObjectDisposedException auslösen kann. Was würde die Ausnahme bedeuten? Dass die Sperrsammlung fertiggestellt wurde? Dass eine Aufgabe in der Warteschlange abgebrochen wurde?

Update: Der Aufruf-Stack sieht so aus:

%Vor%     
Asik 09.04.2014, 15:44
quelle

3 Antworten

11

Das ist eine alte Frage, aber ich werde die vollständige Antwort für jeden hinzufügen, der es in der Zukunft findet. Die Antwort von Eugene ist teilweise richtig; Zu der Zeit müssen Sie mit Visual Studio debuggen, das so konfiguriert wurde, dass es behandelte Framework-Ausnahmen unterbricht.

Der eigentliche Grund, warum Sie bei OperationCanceledException einen Bruch begangen haben, ist jedoch, dass der Code für BlockingCollection<T>.CompleteAdding() folgendermaßen aussieht:

%Vor%

Beachten Sie diese besonderen Zeilen:

%Vor%

die diese Methode aufrufen:

%Vor%

Auch wenn Sie also nicht explizit CancellationToken im Code verwendet wurden, die zugrunde liegende Framework-Code löst eine OperationCanceledException , wenn das BlockingCollection leer ist, wenn CompleteAdding() genannt. Dies bewirkt, dass die GetConsumingEnumerable() -Methode beendet wird. Die Ausnahme wird vom Framework-Code behandelt, und Sie hätten es nicht bemerkt, wenn Sie Ihren Debugger nicht so konfiguriert hätten, dass er ihn abfängt.

Der Grund, warum Sie es nicht replizieren konnten, ist, dass Sie Ihren Aufruf in der Methode CompleteAdding() an Dispose() gesendet haben. Deshalb wurde es nach der Laune des GC aufgerufen.

    
0b101010 07.03.2016, 15:51
quelle
2

Ich kann nur spekulieren, aber ich denke, dass Sie die von Stephen Toub in seinem " Task.Wait und "Inlining" " Blogpost und von Jon Skeet hier .

Wie sieht Ihre Implementierung von TaskScheduler.TryExecuteTaskInline aus? Geben Sie immer false :

zurück, um ein unerwartetes Task-Inlining zu verhindern %Vor%     
Noseratio 10.04.2014 04:31
quelle
1

Diese Ausnahme tritt gelegentlich in der MoveNext () - Methode des GetConsumingEnumerable-Enumerators auf, aber es handelt sich um eine behandelte Ausnahme, daher sollten Sie sie normalerweise nicht sehen.

Vielleicht haben Sie Debugger konfiguriert, um behandelte Ausnahmen zu unterbrechen (in Visual Studio befinden sich diese Optionen im Debug / Exceptions-Menü), in diesem Fall kann der Debugger bei Ausnahmen, die innerhalb von .NET Framework-Funktionen auftreten, sogar brechen.

    
Eugene 17.12.2015 20:48
quelle

Tags und Links