Description
TaskScheduler.TryRunInline does not take into account if ExecutionContext.SuppressFlow is in effect.
Reproduction Steps
Helper.Set("1");
for (int i = 0; i < 10000; i++)
{
await Task.Run(Execute);
}
static void Execute()
{
var suppressFlow = ExecutionContext.SuppressFlow();
var startNew = Task.Factory.StartNew(() =>
{
if (Helper.Get() is { } v) throw new(v);
}
);
startNew.GetAwaiter().GetResult();
suppressFlow.Undo();
}
static class Helper
{
private static readonly AsyncLocal<string?> _asyncLocal = new();
public static string? Get() => _asyncLocal.Value;
public static void Set(string? s) => _asyncLocal.Value = s;
}
Expected behavior
No exceptions
Actual behavior
Randomly throws depending on TaskSchedulers mood.
Regression?
No, but it is more broken in .NET Framework
Known Workarounds
Setting TaskCreationOptions.PreferFairness or TaskCreationOptions.LongRunning prevents the problem, but requires Developer knowledge that any task is executed in suppression.
Configuration
tried on .NET Framework 4.8 & .NET 6/7
Other information
.NET Framework 4.8 will almost certainly fail on first run.
.NET 6/7 will fail within 10-20 runs.
Description
TaskScheduler.TryRunInline does not take into account if ExecutionContext.SuppressFlow is in effect.
Reproduction Steps
Expected behavior
No exceptions
Actual behavior
Randomly throws depending on TaskSchedulers mood.
Regression?
No, but it is more broken in .NET Framework
Known Workarounds
Setting
TaskCreationOptions.PreferFairnessorTaskCreationOptions.LongRunningprevents the problem, but requires Developer knowledge that any task is executed in suppression.Configuration
tried on .NET Framework 4.8 & .NET 6/7
Other information
.NET Framework 4.8 will almost certainly fail on first run.
.NET 6/7 will fail within 10-20 runs.