Catching an exception with Try().Catch() in AsyncLambda doesn't work as expected.
When the task is not finished synchronized, the exception is not caught.
Example
using System.Linq.Expressions;
using DotNext.Linq.Expressions;
using DotNext.Metaprogramming;
using static DotNext.Metaprogramming.CodeGenerator;
var lambda = AsyncLambda(Type.EmptyTypes, typeof(int), AsyncLambdaFlags.None, _ =>
{
Try(() =>
{
var methodInfo = typeof(Methods).GetMethod(nameof(Methods.Throw))!;
var methodResult = Expression.Call(null, methodInfo);
Return(methodResult.Await());
})
.Catch(typeof(Exception), _ =>
{
CallStatic(typeof(Console), nameof(Console.WriteLine), Expression.Constant("Exception caught"));
})
.End();
});
var action = (Func<Task<int>>)lambda.Compile();
await action();
public static class Methods
{
public static async Task<int> Throw()
{
await Task.Yield();
throw new InvalidOperationException("Exception was not caught");
}
}
Expected result
Exception caught
Actual result
Unhandled exception. System.InvalidOperationException: Exception was not caught
at Methods.Throw() in C:\Sources\ConsoleApp2\ConsoleApp2\Program.cs:line 31
at lambda_method2(Closure, PoolingAsyncStateMachine`2&)
at DotNext.Runtime.CompilerServices.PoolingAsyncStateMachine`2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext() in /_/src/DotNext.Metaprogramming/Runtime/CompilerServices/AsyncStateMachine.Pooling.cs:line 363
--- End of stack trace from previous location ---
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
--- End of stack trace from previous location ---
at Program.<Main>$(String[] args) in C:\Sources\ConsoleApp2\ConsoleApp2\Program.cs:line 24
at Program.<Main>(String[] args)
Notes
If you change the method Throw to the following:
public static Task<int> Throw()
{
throw new InvalidOperationException("Exception was not caught");
}
Then the expected result is shown (Exception caught).
If you await the result first with Await(...):
Try(() =>
{
var methodInfo = typeof(Methods).GetMethod(nameof(Methods.Throw))!;
var methodResult = DeclareVariable("result", Expression.Call(null, methodInfo));
Await(methodResult); // <--- Awaiting the result
Return(methodResult.Await()); // <--- Return the result
})
.Catch(typeof(Exception), _ =>
{
CallStatic(typeof(Console), nameof(Console.WriteLine), Expression.Constant("Exception caught"));
})
.End();
Then the expected result is shown (Exception caught). I'm using this currently as workaround.
Catching an exception with
Try().Catch()
in AsyncLambda doesn't work as expected.When the task is not finished synchronized, the exception is not caught.
Example
Expected result
Actual result
Notes
If you change the method
Throw
to the following:Then the expected result is shown (Exception caught).
If you await the result first with
Await(...)
:Then the expected result is shown (Exception caught). I'm using this currently as workaround.