Reputation: 3411
I'm using a TPL dataflow block to process a stream of messages. My data flow network is composed of two blocks, a BufferBlock and an ActionBlock, with the action block being defined as:
_actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 4,
});
If an error occurs inside the action block, I want to let the fault propagate up and exit the application. Later on I'm planning to add in logic here to handle transient errors, but for now, any errors should cause the application to exit with the fault details. To this end, I've added a ContinueWith section like this:
_actionBlock
.Completion
.ContinueWith(dbt =>
{
var inner = dbt.Exception.InnerExceptions.First();
throw inner;
},
TaskContinuationOptions.OnlyOnFaulted
);
The problem is that the "throw inner" doesn't propagate up to anywhere, the application just carries on as if the exception was being swallowed. I don't have any further exception handlers in my code. As an experiment I've tried
Re-throwing the exception using
Dispatcher.CurrentDispatcher.Invoke(() => throw ...)
Checking that the ContinueWith contents are running on the UI thread.
Handling any top level exceptions using:
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(ToplevelHandler);
(The exception thrown never reaches TopLevelHandler)
None of these has helped.
How can I make the exception that I throw inside the ContinueWith function propagate to the top of the application and make the application exit with an error message?
Upvotes: 2
Views: 1307
Reputation: 3761
Quote from Concurrency in C# Cookbook (Stephen Cleary):
To catch exceptions from a Dataflow block, await its Completion property. The Completion property returns a Task that will complete when the block is completed, and if the block faults, the Completion task is also faulted.
actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 4,
});
await actionBlock.Completion;
Upvotes: 4