Skip to content

Instantly share code, notes, and snippets.

@davidfowl
Last active August 31, 2022 01:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidfowl/a0fd764213a77d1824f58a32d582bd0b to your computer and use it in GitHub Desktop.
Save davidfowl/a0fd764213a77d1824f58a32d582bd0b to your computer and use it in GitHub Desktop.
Async local gotchas
using (var thing = new DisposableThing())
{
// Make the disposable object available ambiently
DisposableThing.Current = thing;
Dispatch();
// We're about the dispose the object so make sure nobody else captures this instance
DisposableThing.Current = null;
}
void Dispatch()
{
// Task.Run will capture the current execution context (which means async locals are captured in the callback)
_ = Task.Run(async () =>
{
// Delay for a second then log
await Task.Delay(1000);
Log();
});
}
void Log()
{
try
{
// Get the current value and make sure it's not null before reading the value
var thing = DisposableThing.Current;
if (thing is not null)
{
Console.WriteLine($"Logging ambient value {thing.Value}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Console.ReadLine();
class DisposableThing : IDisposable
{
private static AsyncLocal<DisposableThing?> _current { get; } = new();
private bool _disposed;
public static DisposableThing? Current
{
get => _current.Value;
set
{
_current.Value = value;
}
}
public int Value
{
get
{
if (_disposed) throw new ObjectDisposedException(GetType().FullName);
return 1;
}
}
public void Dispose()
{
_disposed = true;
}
}
AmbientValues.Current = new();
Parallel.For(0, 10, i =>
{
AmbientValues.Current[i.ToString()] = "processing";
Log();
AmbientValues.Current[i.ToString()] = "done";
});
void Log()
{
foreach (var pair in AmbientValues.Current)
{
Console.WriteLine(pair);
}
}
class AmbientValues
{
private static AsyncLocal<Dictionary<string, string>> _current { get; } = new();
public static Dictionary<string, string> Current
{
get => _current.Value!;
set => _current.Value = value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment