Skip to content

Commit 3e7c20f

Browse files
eduardo-vpEduardo Manuel Velarde Polarkouvel
authored andcommitted
Stop counting work items from ThreadPoolTypedWorkItemQueue for ThreadPool.CompletedWorkItemCount (dotnet#106854)
* Stop counting work items from ThreadPoolTypedWorkItemQueue as completed work items * Fix CompletedWorkItemCount * Update src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs Co-authored-by: Koundinya Veluri <[email protected]> * Run CompletedWorkItemCountTest on Windows only --------- Co-authored-by: Eduardo Manuel Velarde Polar <[email protected]> Co-authored-by: Koundinya Veluri <[email protected]>
1 parent 4196cd2 commit 3e7c20f

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1393,7 +1393,11 @@ void IThreadPoolWorkItem.Execute()
13931393
currentThread.ResetThreadPoolThread();
13941394
}
13951395

1396-
ThreadInt64PersistentCounter.Add(tl.threadLocalCompletionCountObject!, completedCount);
1396+
// Discount a work item here to avoid counting most of the queue processing work items
1397+
if (completedCount > 1)
1398+
{
1399+
ThreadInt64PersistentCounter.Add(tl.threadLocalCompletionCountObject!, completedCount - 1);
1400+
}
13971401
}
13981402
}
13991403

src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,33 @@ static async Task RunAsyncIOTest()
14401440
}, ioCompletionPortCount.ToString()).Dispose();
14411441
}
14421442

1443+
1444+
[ConditionalFact(nameof(IsThreadingAndRemoteExecutorSupported))]
1445+
[PlatformSpecific(TestPlatforms.Windows)]
1446+
public static unsafe void ThreadPoolCompletedWorkItemCountTest()
1447+
{
1448+
// Run in a separate process to test in a clean thread pool environment such that we don't count external work items
1449+
RemoteExecutor.Invoke(() =>
1450+
{
1451+
using var manualResetEvent = new ManualResetEventSlim(false);
1452+
1453+
var overlapped = new Overlapped();
1454+
NativeOverlapped* nativeOverlapped = overlapped.Pack((errorCode, numBytes, innerNativeOverlapped) =>
1455+
{
1456+
Overlapped.Free(innerNativeOverlapped);
1457+
manualResetEvent.Set();
1458+
}, null);
1459+
1460+
ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped);
1461+
manualResetEvent.Wait();
1462+
1463+
// Allow work item(s) to be marked as completed during this time, should be only one
1464+
ThreadTestHelpers.WaitForCondition(() => ThreadPool.CompletedWorkItemCount == 1);
1465+
Thread.Sleep(50);
1466+
Assert.Equal(1, ThreadPool.CompletedWorkItemCount);
1467+
}).Dispose();
1468+
}
1469+
14431470
public static bool IsThreadingAndRemoteExecutorSupported =>
14441471
PlatformDetection.IsThreadingSupported && RemoteExecutor.IsSupported;
14451472

0 commit comments

Comments
 (0)