The program below behaves as expected for three retries but then crashes:
$ ./PollyTest/bin/Debug/net8.0/PollyTest.exe
Hello, World!
retry number 0
retry number 1
retry number 2
Unhandled exception. System.ApplicationException: work work
at Program.<<Main>$>g__WorkAsync|0_1(CancellationToken token) in C:\git\test\pollytest\PollyTest\PollyTest\Program.cs:line 34
at Program.<>c.<<<Main>$>b__0_0>d.MoveNext() in C:\git\test\pollytest\PollyTest\PollyTest\Program.cs:line 25
--- End of stack trace from previous location ---
at Polly.ResiliencePipeline.<>c.<<ExecuteAsync>b__3_0>d.MoveNext()
--- End of stack trace from previous location ---
at Polly.Outcome`1.GetResultOrRethrow()
at Polly.ResiliencePipeline.ExecuteAsync(Func`2 callback, CancellationToken cancellationToken)
at Program.<Main>$(String[] args) in C:\git\test\pollytest\PollyTest\PollyTest\Program.cs:line 23
at Program.<Main>(String[] args)
$
with the following source code:
using Polly.Retry;
using Polly;
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
var retryOptions = new RetryStrategyOptions
{
BackoffType = DelayBackoffType.Exponential,
Delay = TimeSpan.FromMilliseconds(100),
MaxDelay = TimeSpan.FromSeconds(60),
OnRetry = arguments =>
{
Console.WriteLine($"retry number {arguments.AttemptNumber}");
return default;
},
ShouldHandle = args => PredicateResult.True(),
};
var pipeline = new ResiliencePipelineBuilder()
.AddRetry(retryOptions)
.Build();
await pipeline.ExecuteAsync(async token =>
{
await WorkAsync(token);
}, CancellationToken.None);
return;
///////////////////////////////////
static Task WorkAsync(CancellationToken token)
{
throw new ApplicationException("work work");
}
When running in debug mode in Visual Studio, the following is printed in the Debug output
...
'PollyTest.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.2\System.ObjectModel.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'PollyTest.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.2\System.Collections.Concurrent.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'PollyTest.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.2\System.Private.Uri.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Exception thrown: 'System.ApplicationException' in PollyTest.dll
Exception thrown: 'System.ApplicationException' in PollyTest.dll
Exception thrown: 'System.ApplicationException' in PollyTest.dll
Exception thrown: 'System.ApplicationException' in PollyTest.dll
Exception thrown: 'System.ApplicationException' in System.Private.CoreLib.dll
An exception of type 'System.ApplicationException' occurred in System.Private.CoreLib.dll but was not handled in user code
work work
so obviously all Exception thrown: ... in PollyTest.dll are captured and handled as expected but Exception thrown: ... in System.Private.CoreLib.dll is not. But why is suddenly System.Private.CoreLib.dll involved? How can I avoid?
This is with Polly version 8.3.0.
Your observed behavior has nothing to do with Polly. If you remove the retry logic from your application and execute directly the
WorkAsyncchange from
to
then you will see the exact same behavior.
The
System.ApplicationExceptionis defined inside theSystem.Runtime.dllwhich is a reference assembly. The implementation assembly of this type isSystem.Private.CoreLib.dll.So, that's the reason why do you see
System.Private.CoreLib.dllin your standard output / error.