Closed latop2604 closed 12 months ago
This is the result of the state-machine rewrite on the first await
; fixing
example that shows the problem is below; I'm investigating options
using System;
using System.Threading.Tasks;
// fine and dandy, dandy and fine
Console.WriteLine();
Console.WriteLine("sync");
var foo = new Foo(1);
Console.WriteLine($"After .ctor (1): {foo.State}"); // 1
foo.DoTheThing(2);
Console.WriteLine($"After work (2): {foo.State}"); // 2
foo.DoTheThing(3);
Console.WriteLine($"After work (3): {foo.State}"); // 3
// ho hum, mutations to state don't get preserved
Console.WriteLine();
Console.WriteLine("async (but actually sync)");
foo = new Foo(1);
Console.WriteLine($"After .ctor (1): {foo.State}"); // 1
await foo.DoTheThingAsync(true, 2);
Console.WriteLine($"After work (2): {foo.State}"); // 1 - expected 2
await foo.DoTheThingAsync(true, 3);
Console.WriteLine($"After work (3): {foo.State}"); // 1 - expected 3
// nor here
Console.WriteLine();
Console.WriteLine("true async");
foo = new Foo(1);
Console.WriteLine($"After .ctor (1): {foo.State}"); // 1
await foo.DoTheThingAsync(false, 2);
Console.WriteLine($"After work (2): {foo.State}"); // 1 - expected 2
await foo.DoTheThingAsync(false, 3);
Console.WriteLine($"After work (3): {foo.State}"); // 1 - expected 3
// fine again
Console.WriteLine();
Console.WriteLine("back to sync");
foo = new Foo(1);
Console.WriteLine($"After .ctor (1): {foo.State}"); // 1
foo.DoTheThing(2);
Console.WriteLine($"After work (2): {foo.State}"); // 2
foo.DoTheThing(3);
Console.WriteLine($"After work (3): {foo.State}"); // 3
struct Foo // intentionally mutable
{
public Foo(int state) => State = state;
public int State { get; private set; }
public void DoTheThing(int state) => State = state;
public async Task DoTheThingAsync(bool sync, int state)
{
if (!sync) { await Task.Yield(); }
State = state;
}
}
Hello
I'm trying
DapperAOT
with the new interceptor mode and I spotted an issue that occurs only in async mode.The problem occurs in
Command<TArgs>.QueryBufferedAsync
when invokingawait state.ExecuteReaderAsync(...)
. This method is supposed to assign the Reader field of theQueryState
struct. However, it seem that the struct is copied (by value) during the async call, causing the reader to be set on a separate instance. When the execution returns toCommand<TArgs>.QueryBufferedAsync
, the originalQueryState
remains unchanged, and the Reader field stays null.I attempted to modify QueryState from a struct to a class (and replaced all instances of QueryState state = default; with QueryState state = new();), and it worked.
Although I'm not expert enough to resolve this issue on my own, I hope my findings will be helpful to you.
Main branch commit 90701185fa726a680947a4216076b1f1223fa9d4
Sorry for my (ChatGPT enhanced) English