An attempt was made to transition a task to a final state when it had already completed
See original GitHub issuePartially related to my other issue (#14), when I fixed the issue in my code the state machine seems to become invalid at some point (I guess the return might not be valid). I get this exception + stack trace:
at void DotNext.Runtime.CompilerServices.AsyncStateMachine<TState, TResult>.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext() in /_/src/DotNext.Metaprogramming/Runtime/CompilerServices/AsyncStateMachine.cs:line 380 at void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult>+AsyncStateMachineBox<TStateMachine>.MoveNext(Thread threadPoolThread) at Action System.Runtime.CompilerServices.TaskAwaiter.OutputWaitEtwEvents(Task task, Action continuation)+(Action innerContinuation, Task innerTask) => { } at void System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, object state, ref Task currentTask) at void System.Threading.Tasks.Task.ThrowAsync(Exception exception, SynchronizationContext targetContext)+(object state) => { } at void System.Threading.QueueUserWorkItemCallback.s_executionContextShim(QueueUserWorkItemCallback quwi) at void System.Threading.QueueUserWorkItemCallback.Execute() at bool System.Threading.ThreadPoolWorkQueue.Dispatch()
This is my code for generating the lambda:
var funcSignature = typeof(Func<,,,>).MakeGenericType(writerType, typeof(EntityBase),
typeof(CancellationToken), typeof(Task<>).MakeGenericType(typeof(byte[])));
var method = typeof(CodeGenerator).GetMethod(nameof(CodeGenerator.AsyncLambda))
.MakeGenericMethod(funcSignature).Unreflect();
var compileMethod = typeof(Expression<>).MakeGenericType(funcSignature)
.GetMethod(nameof(LambdaExpression.Compile), BindingFlags.Public | BindingFlags.Instance, null,
CallingConventions.Any, Type.EmptyTypes, null).Unreflect();
finalExpression = method(null, (Action<LambdaContext>)GenerateAsyncLambda);
finalExpression = compileMethod(finalExpression);
void GenerateAsyncLambda(LambdaContext c)
{
var localWriter = DeclareVariable("writer", c[0]);
var localEntity = DeclareVariable("e", c[1]);
var localToken = DeclareVariable("token", c[2]);
var actualEntity = DeclareVariable(entityType, "actualEntity");
Assign(actualEntity, Expression.Convert(localEntity, entityType));
ParameterReplacer replacer = new ParameterReplacer(localWriter, actualEntity, localToken, entityType);
foreach (var expr in writerExpressions)
Await(replacer.Visit(expr), true);
}
EDIT: I tried adding Return()
at the end, but that’s not working either.
Issue Analytics
- State:
- Created 3 years ago
- Comments:13
I realized the difference between my sample and the actual application but even when I changed it to the very same implementation I can’t reproduce the issue. What I found out though is that this seems to be a threading issue which I now doubt to be originating from within DotNext. When I await my parallel tasks instead of spawning them and letting it all work concurrently, it does not throw any exception and run a thousand times faster at that.
I can still show you the example if you want, but I guess you would be better off just releasing the new version with current fixes and ignore this issue.
Okay, you were right. I mixed things up - obviously it has to be
Func<,,,Task>
. TheFunc<byte[]>
was from the generated expressions which are awaited inside that async lambda construct. Thanks!