diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs index bfa8ccd86802c..246ed5b92f85a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs @@ -745,7 +745,7 @@ private async Task WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int public ConfiguredNoThrowAwaiter(Task task) => _task = task; public ConfiguredNoThrowAwaiter GetAwaiter() => this; public bool IsCompleted => _task.IsCompleted; - public void GetResult() { } + public void GetResult() => _task.MarkExceptionsAsHandled(); public void UnsafeOnCompleted(Action continuation) => _task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(continuation); public void OnCompleted(Action continuation) => _task.ConfigureAwait(false).GetAwaiter().OnCompleted(continuation); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index 458c914773cbc..8a21b34ddb01c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @@ -1863,6 +1863,12 @@ internal List GetExceptionDispatchInfos() return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null } + /// Marks any exceptions stored in the Task as having been handled. + internal void MarkExceptionsAsHandled() + { + Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.MarkAsHandled(calledFromFinalizer: false); + } + /// /// Throws an aggregate exception if the task contains exceptions. /// diff --git a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs index 2682166b24c51..7aabd01c39f1e 100644 --- a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs +++ b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Threading.Tests @@ -615,5 +617,28 @@ public static void TestConcurrentWaitAndWaitAsync(int syncWaiters, int asyncWait semaphore.Release(totalWaiters / 2); Task.WaitAll(tasks); } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void WaitAsync_Timeout_NoUnhandledException() + { + RemoteExecutor.Invoke(async () => + { + Exception error = null; + TaskScheduler.UnobservedTaskException += (s, e) => Volatile.Write(ref error, e.Exception); + + var sem = new SemaphoreSlim(0); + for (int i = 0; i < 2; ++i) + { + await sem.WaitAsync(1); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + if (Volatile.Read(ref error) is Exception e) + { + throw e; + } + }).Dispose(); + } } }