-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
I encountered a NullReferenceException thrown from within System.Threading.Tasks.Task.ScheduleAndStart
as it was executing a Task generated by a Parallel.For
call.
It appears to be due to simultaneous calls to the Start
and Wait
methods on the task, from different threads.
The exception is thrown by some event logging code, and so only happens if TPL task events are enabled.
Reproduction Steps
The following console app reliably reproduces the exception when run under Visual Studio debugger:
var scheduler = new ConcurrentExclusiveSchedulerPair().ConcurrentScheduler;
bool stop = false;
Task? taskField = null;
var waitTask = new Task(() =>
{
while (!stop)
{
taskField?.Wait();
}
});
waitTask.Start(scheduler);
while (!Console.KeyAvailable)
{
taskField = new Task(() => { });
taskField.Start(scheduler);
}
stop = true;
I have also reproduced it by running the program outside the debugger and then starting a PerfView collection with TPL task events enabled.
Expected behavior
The above code should execute without error until the user terminates it with a keypress.
Actual behavior
A NullReferenceException is thrown:
System.ArgumentNullException
HResult=0x80004003
Message=Value cannot be null. (Parameter '@delegate')
Source=System.Private.CoreLib
StackTrace:
at System.ArgumentNullException.Throw(String paramName)
at System.Diagnostics.DiagnosticMethodInfo.Create(Delegate delegate)
at System.Threading.Tasks.LoggingExtensions.GetMethodName(Delegate delegate)
at System.Threading.Tasks.Task.ScheduleAndStart(Boolean needsProtection)
at Program.<Main>$(String[] args) in C:\git\TaskNRE\TaskNRE\Program.cs:line 19
Regression?
I don't think so - it's reproducible in previous .NET versions and in .NET Framework 4.7.2.
Known Workarounds
No response
Configuration
.NET 9.0.8 (but happens in the two other versions I tried)
Windows 11 Enterprise Version 10.0.22631 Build 22631
x64
Other information
The exception is thrown from this line:
runtime/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs
Line 1684 in 0e3562e
TplEventSource.Log.TraceOperationBegin(this.Id, "Task: " + m_action.GetMethodName(), 0); |
m_action
is null. Note the Debug.Assert in the previous line that m_action
is not null.
I hypothesise that the call to Wait
on a separate thread has caused the task to be executed to completion inline, at which point the m_action
field is set to null.
It is not clear to me if there are any consequences to this if TPL logging is turned off.