According to the source code of Task
https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs,1483
So Task
uses ManualResetEventSlim
kernel synchronization construct internally
internal ManualResetEventSlim CompletedEvent
{
get
{
ContingentProperties contingentProps = EnsureContingentPropertiesInitialized();
if (contingentProps.m_completionEvent == null)
{
bool wasCompleted = IsCompleted;
ManualResetEventSlim newMre = new ManualResetEventSlim(wasCompleted); // <----------------
if (Interlocked.CompareExchange(ref contingentProps.m_completionEvent, newMre, null) != null)
{
// Someone else already set the value, so we will just close the event right away.
newMre.Dispose();
}
else if (!wasCompleted && IsCompleted)
{
// We published the event as unset, but the task has subsequently completed.
// Set the event's state properly so that callers don't deadlock.
ContingentProperties.SetEvent(newMre);
}
}
return contingentProps.m_completionEvent;
}
}
But isn't that running a Task means threadpool places the "work item" (represented as Task in high level) to the global/local queue then it will picked up by a worker thread to run? is there a need to use any kernel thread synchronization construct? I mean it synchronize with whom? what's the purpose of using a kernel construct here?
Is there a need to use any kernel thread synchronization construct?
Yes, for the Wait
method. When you call Wait
, you want to block the current thread until the Task
completes on another thread. The ManualResetEventSlim
performs the role of blocking the current thread, until a signal comes from the completing thread so that the current thread can be unblocked.
Isn't that running a
Task
means threadpool places the "work item" (represented as Task in high level) to the global/local queue then it will picked up by a worker thread to run?
This is the case with the delegate-based tasks, that were introduced with the .NET Framework 4.0 at 2010. The next .NET release (.NET Framework 4.5 at 2012) introduced the async
/await
technology, that made promise-style tasks more prominent. These tasks can represent anything and not just the completion of a delegate. Most tasks today fall in the second category. For example the File.ReadAllTextAsync
returns a promise-style Task
. There is no thread tied to the Task
for the majority of the time that this operation is in-flight.