public ConfiguredNoThrowAwaiter(Task<T> task) => _task = task;
public ConfiguredNoThrowAwaiter<T> 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);
}
return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null
}
+ /// <summary>Marks any exceptions stored in the Task as having been handled.</summary>
+ internal void MarkExceptionsAsHandled()
+ {
+ Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.MarkAsHandled(calledFromFinalizer: false);
+ }
+
/// <summary>
/// Throws an aggregate exception if the task contains exceptions.
/// </summary>
// 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
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();
+ }
}
}