If you could change the interface (which was not a constraint for me when I had a similar problem), to me it seemed like Lazy<Task>
could be used to solve this OK. So I tried it out.
It works, at least for what I want 'the current task' to mean. But it is subtle code, because AsyncMethodThatYouWantToRun
has to do Task.Yield()
.
If you don't yield, it will fail with System.AggregateException: 'One or more errors occurred. (ValueFactory attempted to access the Value property of this instance.)'
Lazy<Task> eventuallyATask = null; // silly errors about uninitialized variables :-/
eventuallyATask = new Lazy<Task>(
() => AsyncMethodThatYouWantToRun(eventuallyATask));
Task t = eventuallyATask.Value; // actually start the task!
async Task AsyncMethodThatYouWantToRun(Lazy<Task> lazyThisTask)
{
await Task.Yield(); // or else, the 'task' object won't finish being created!
Task thisTask = lazyThisTask.Value;
Console.WriteLine("you win! Your task got a reference to itself");
}
t.Wait();
Alternatively instead of the subtlety of Task.Yield
we could just go tasks all the way, and use TaskCompletionSource<Task>
to solve it. (eliminating any potential errors/deadlocks, since our task safely releases the thread until it can know itself!)
var eventuallyTheTask = new TaskCompletionSource<Task>();
Task t = AsyncMethodThatYouWantToRun(eventuallyTheTask.Task); // start the task!
eventuallyTheTask.SetResult(t); //unblock the task and give it self-knowledge
async Task AsyncMethodThatYouWantToRun(Task<Task> thisTaskAsync)
{
Task thisTask = await thisTaskAsync; // gets this task :)
Console.WriteLine("you win! Your task got a reference to itself (== 't')");
}
t.Wait();