ErythroGuild / irene

<Erythro>'s server admin bot.
Mozilla Public License 2.0
0 stars 0 forks source link

See if `TaskQueue.Run(Task<Task>)` can be simplified further #311

Open Ernest314 opened 2 years ago

Ernest314 commented 2 years ago

The naive case of passing a simple Task (as an async lambda: .Run(async () => {}), instead of .Run(new Task<Task>(async () => {}))) doesn't work, because the result monitoring task (TaskPair.Result) returns as finished before the actual action finishes executing.

Intuitively, however, it feels like you should be able to just pass in a Task? Because it is possible to make it sorta work, the passed Task just starts executing immediately--there's probably a way to avoid that through wrapping the passed Task or wrapping the result Task or something??


See this Stack Overflow answer for insight on the nested Task wrapping (Task<Task<TResult>>): https://stackoverflow.com/a/61800690/1292093

I think I saw the info about tasks executing immediately being a result of async delegate quirks on a stack overflow answer that didn't have a lot of votes, but I cannot for the life of me find it again :/

Ernest314 commented 2 years ago

This could have to do with async lambdas automatically converting to async void type? See: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/

(although that may be out of date)

(also there's a nice chart here but it's not the most relevant? https://blog.stephencleary.com/2014/02/synchronous-and-asynchronous-delegate.html)

Ernest314 commented 2 years ago

also kinda unhelpful page: https://blog.stephencleary.com/2014/05/a-tour-of-task-part-1-constructors.html

but! mentions considering Task.Factory.FromAsync and TaskCompletionSource

Ernest314 commented 2 years ago

also consider:

(Unwrap)

Ernest314 commented 2 years ago

Actually Unwrap() might be exactly what we need here...