// We want to make sure that holding on to the resulting Task doesn't keep
// that finalizable object alive.
- var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+ bool finalized = false;
Task t = null;
GC.KeepAlive(s); // keep s referenced by the state machine
}
- var state = new InvokeActionOnFinalization { Action = () => tcs.SetResult() };
+ var state = new InvokeActionOnFinalization { Action = () => Volatile.Write(ref finalized, true) };
var al = new AsyncLocal<object>() { Value = state }; // ensure the object is stored in ExecutionContext
t = YieldOnceAsync(state); // ensure the object is stored in the state machine
al.Value = null;
await t; // wait for the async method to complete and clear out its state
await Task.Yield(); // ensure associated state is not still on the stack as part of the antecedent's execution
- for (int i = 0; i < 2; i++)
+ for (int i = 0; i < 10 && !Volatile.Read(ref finalized); i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
- try
- {
- await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60));
- }
- catch (Exception e)
+ if (!Volatile.Read(ref finalized))
{
- Environment.FailFast("Look at the created dump", e);
+ Environment.FailFast("Look at the created dump");
}
GC.KeepAlive(t); // ensure the object is stored in the state machine
// We want to make sure that holding on to the resulting Task doesn't keep
// that finalizable object alive.
- var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+ bool finalized = false;
Task t = null;
Thread runner = new Thread(() =>
{
- var state = new InvokeActionOnFinalization { Action = () => tcs.SetResult() };
+ var state = new InvokeActionOnFinalization { Action = () => Volatile.Write(ref finalized, true) };
var al = new AsyncLocal<object>(){ Value = state }; // ensure the object is stored in ExecutionContext
t = Task.Run(() => { }); // run a task that'll capture EC
al.Value = null;
await t; // wait for the task method to complete and clear out its state
- for (int i = 0; i < 2; i++)
+ for (int i = 0; i < 10 && !Volatile.Read(ref finalized); i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
- try
- {
- await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60)); // finalizable object should have been collected and finalized
- }
- catch (Exception e)
+ if (!Volatile.Read(ref finalized))
{
- Environment.FailFast("Look at the created dump", e);
+ Environment.FailFast("Look at the created dump");
}
GC.KeepAlive(t); // ensure the object is stored in the state machine