Blocking Collection Issue
-
My requirements are simple. I need something with the following: * queue like behavior (FIFO) * thread-safe * blocking behavior for get item method * blocking get item method should be cancellable (cancellationtoken, bool, etc) * blocking behavior should be 0% CPU / non spinning (no sleeps) * high performance So, naturally, I went with BlockingCollectionT. This works fine, and meets all my requirements, however, when you use the cancellable Take(CancellationToken) and cancel the operation, you get 3 exceptions: A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll A first chance exception of type 'System.OperationCanceledException' occurred in System.dll The first 2 are caught inside of the framework and the 3rd I catch in my code. This causes people to complain :(. I tried explaining this is "expected behavior", but you know people... I looked at BlockingCollectionT in ILSpy and it doesn't seem like its going to be possible to bypass the exception throwing. GOD, I hate APIs that throw exceptions for "normal" behavior. Seems like everything that uses the cancellationtoken throws exceptions on cancellation? Any other options that don't throw exceptions on a cancellation?
-
My requirements are simple. I need something with the following: * queue like behavior (FIFO) * thread-safe * blocking behavior for get item method * blocking get item method should be cancellable (cancellationtoken, bool, etc) * blocking behavior should be 0% CPU / non spinning (no sleeps) * high performance So, naturally, I went with BlockingCollectionT. This works fine, and meets all my requirements, however, when you use the cancellable Take(CancellationToken) and cancel the operation, you get 3 exceptions: A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll A first chance exception of type 'System.OperationCanceledException' occurred in System.dll The first 2 are caught inside of the framework and the 3rd I catch in my code. This causes people to complain :(. I tried explaining this is "expected behavior", but you know people... I looked at BlockingCollectionT in ILSpy and it doesn't seem like its going to be possible to bypass the exception throwing. GOD, I hate APIs that throw exceptions for "normal" behavior. Seems like everything that uses the cancellationtoken throws exceptions on cancellation? Any other options that don't throw exceptions on a cancellation?
"Blocking" and "High performance" are not very compatible.
SledgeHammer01 wrote:
Any other options that don't throw exceptions on a cancellation?
Catching exceptions is not that expensive. It is with the debugger attached, but you can throw and handle quite a lot of exceptions in a single second if there's no debugger attached.
SledgeHammer01 wrote:
Seems like everything that uses the cancellationtoken throws exceptions on cancellation?
Implement your own, disallow cancelling; problem solved. It would be a cool subject for a CodeProject-contest; writing a fast, multithreaded queue.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
-
My requirements are simple. I need something with the following: * queue like behavior (FIFO) * thread-safe * blocking behavior for get item method * blocking get item method should be cancellable (cancellationtoken, bool, etc) * blocking behavior should be 0% CPU / non spinning (no sleeps) * high performance So, naturally, I went with BlockingCollectionT. This works fine, and meets all my requirements, however, when you use the cancellable Take(CancellationToken) and cancel the operation, you get 3 exceptions: A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll A first chance exception of type 'System.OperationCanceledException' occurred in System.dll The first 2 are caught inside of the framework and the 3rd I catch in my code. This causes people to complain :(. I tried explaining this is "expected behavior", but you know people... I looked at BlockingCollectionT in ILSpy and it doesn't seem like its going to be possible to bypass the exception throwing. GOD, I hate APIs that throw exceptions for "normal" behavior. Seems like everything that uses the cancellationtoken throws exceptions on cancellation? Any other options that don't throw exceptions on a cancellation?
SledgeHammer01 wrote:
* blocking get item method should be cancellable (cancellationtoken, bool, etc)
Never understood that need. That can only apply if getting the item requires acquiring other resources and in that case, especially given 5, then either make the caller responsible for that or wrap it is a proxy and that does it.
SledgeHammer01 wrote:
I hate APIs that throw exceptions for "normal" behavior.
Its a generic class/API which means if there is a failure mode then it must throw exceptions. If that isn't desirable then write your own. Not that hard and I suspect there are a vast number of examples on the internet.
-
SledgeHammer01 wrote:
* blocking get item method should be cancellable (cancellationtoken, bool, etc)
Never understood that need. That can only apply if getting the item requires acquiring other resources and in that case, especially given 5, then either make the caller responsible for that or wrap it is a proxy and that does it.
SledgeHammer01 wrote:
I hate APIs that throw exceptions for "normal" behavior.
Its a generic class/API which means if there is a failure mode then it must throw exceptions. If that isn't desirable then write your own. Not that hard and I suspect there are a vast number of examples on the internet.
jschell wrote:
Never understood that need. That can only apply if getting the item requires acquiring other resources and in that case, especially given 5, then either make the caller responsible for that or wrap it is a proxy and that does it.
I have a worker thread that monitors the queue. There is not always something in the queue. In fact, most of the time, it will be empty or close to it. Clearly, I should not spin the CPU when the queue is empty. As for being able to cancel the blocking operation, well... if you wait on a syncronization object indefinitely (the blocking part), it keeps the thread alive (which will keep the process alive) [EDIT: unless the thread is a background thread]. Not a desirable behavior when you, say, want to be able to shut down your app :). Using a timeout is also not a solution, as if you set your timeout too low, you'll spin the CPU, and if you set it too high, you'll have that annoying behavior of your app taking a long time to shut down.
jschell wrote:
Its a generic class/API which means if there is a failure mode then it must throw exceptions.
I wouldn't consider cancelling a blocking operation to be a failure if the cancellation was intended. But some would...
jschell wrote:
Not that hard and I suspect there are a vast number of examples on the internet.
You'd be surprised ;).