Consider the snippet bellow.
A form adds a BusyForm to the queue and later on, when the form is done, it sets the result for the TCS, marking it as complete, without removing the item from the queue.
After a while, something happens and we need to wait for all busy forms, so we await each TCS task
in the queue. But surprise, surprise .. GC grabbed it.
Why? Isn't it referenced by the queue?
static class Global
{
public static ConcurrentQueue<BusyForm> BusyForms = new ConcurrentQueue<BusyForm>();
public class BusyForm
{
public string Name;
public TaskCompletionSource<bool> Done = new TaskCompletionSource<bool>();
public BusyForm(string name)
{
this.Name = name;
}
}
}
// somewhere else when form is done
busyForm.Done.SetResult(true);
// after a while, when required
while(!Global.BusyForms.IsEmpty)
{
Global.BusyForms.TryPeek(out busyForm);
await busyForm.Done.Task; // can be disposed by GC if finished a long time ago
Global.BusyForms.TryDequeue(out busyForm);
}