From da10cce4500a5ff6f06ea3468cbb697cc43207b0 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 9 Mar 2021 16:07:36 -0500 Subject: [PATCH] Add Task.WaitAsync methods --- .../Threading/Tasks/TaskTimeoutExtensions.cs | 44 ------ .../System/IO/StreamConformanceTests.cs | 9 +- .../System/Net/Http/GenericLoopbackServer.cs | 2 +- .../Net/Http/Http2LoopbackConnection.cs | 5 +- .../System/Net/Http/Http2LoopbackServer.cs | 4 +- .../System/Net/Http/Http3LoopbackServer.cs | 2 +- .../Net/Http/HttpAgnosticLoopbackServer.cs | 4 +- .../Net/Http/HttpClientHandlerTest.Proxy.cs | 2 +- .../System/Net/Http/HttpClientHandlerTest.cs | 2 +- .../tests/System/Net/Http/TestHelper.cs | 2 + .../Threading/Tasks/TaskTimeoutExtensions.cs | 98 ++++--------- .../tests/PhysicalFileProviderTests.cs | 2 +- .../src/Deployers/SelfHostDeployer.cs | 2 +- .../tests/FunctionalTests/ShutdownTests.cs | 4 +- ...Generic.Tests.ConcurrentAccessDetection.cs | 2 +- .../tests/BackgroundWorkerTests.cs | 3 +- .../src/System.Diagnostics.Process.csproj | 4 - .../System/Diagnostics/AsyncStreamReader.cs | 20 +-- .../src/System/Diagnostics/Process.Unix.cs | 10 +- .../src/System/Diagnostics/Process.Windows.cs | 10 +- .../src/System/Diagnostics/Process.cs | 14 +- .../FunctionalTests/WinHttpHandlerTest.cs | 8 +- .../HttpClientHandlerTest.Http2.cs | 48 +++--- .../HttpClientHandlerTest.Http3.cs | 6 +- .../FunctionalTests/SocketsHttpHandlerTest.cs | 30 ++-- .../tests/HttpListenerTests.cs | 4 +- .../tests/HttpRequestStreamTests.cs | 2 +- .../tests/Functional/SmtpClientTest.cs | 4 +- .../Net/NetworkInformation/Ping.Unix.cs | 50 +++---- .../tests/FunctionalTests/MsQuicTests.cs | 2 +- .../FunctionalTests/QuicListenerTests.cs | 2 +- .../tests/FunctionalTests/QuicStreamTests.cs | 4 +- .../ClientAsyncAuthenticateTest.cs | 2 +- .../NegotiateStreamKerberosTest.cs | 6 +- .../ServerAsyncAuthenticateTest.cs | 4 +- .../FunctionalTests/SslStreamAlertsTest.cs | 16 +- .../FunctionalTests/SslStreamAlpnTests.cs | 2 +- .../SslStreamCredentialCacheTest.cs | 2 +- .../tests/FunctionalTests/SslStreamEKUTest.cs | 6 +- .../SslStreamNegotiatedCipherSuiteTest.cs | 6 +- .../SslStreamNetworkStreamTest.cs | 2 +- .../SslStreamSchSendAuxRecordTest.cs | 2 +- .../SslStreamStreamToStreamTest.cs | 2 +- .../FunctionalTests/TestConfiguration.cs | 1 + .../tests/FunctionalTests/Accept.cs | 2 +- .../tests/FunctionalTests/Connect.cs | 2 +- .../tests/FunctionalTests/ReceiveFrom.cs | 8 +- .../FunctionalTests/ReceiveMessageFrom.cs | 10 +- .../tests/FunctionalTests/SelectTest.cs | 2 +- .../tests/FunctionalTests/SendFile.cs | 4 +- .../SendReceive/SendReceive.cs | 4 +- .../SendReceive/SendReceiveMisc.cs | 11 +- .../FunctionalTests/SocketOptionNameTest.cs | 12 +- .../tests/WebClientTest.cs | 6 +- .../tests/SendReceiveTest.cs | 4 +- .../src/Resources/Strings.resx | 4 +- .../src/System/Threading/Tasks/Future.cs | 41 ++++++ .../src/System/Threading/Tasks/Task.cs | 138 ++++++++++++++++-- .../src/System/ThrowHelper.cs | 6 +- .../System.Runtime/ref/System.Runtime.cs | 6 + .../TestService.cs | 3 +- .../tests/TestServiceProvider.cs | 2 +- .../AsyncTaskMethodBuilderTests.cs | 2 +- .../TaskAwaiterTests.cs | 112 ++++++++++++++ .../tests/Task/ExecutionContextFlowTest.cs | 4 +- 65 files changed, 498 insertions(+), 341 deletions(-) delete mode 100644 src/libraries/Common/src/System/Threading/Tasks/TaskTimeoutExtensions.cs diff --git a/src/libraries/Common/src/System/Threading/Tasks/TaskTimeoutExtensions.cs b/src/libraries/Common/src/System/Threading/Tasks/TaskTimeoutExtensions.cs deleted file mode 100644 index e94b338ea4ecd..0000000000000 --- a/src/libraries/Common/src/System/Threading/Tasks/TaskTimeoutExtensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Threading.Tasks -{ - /// - /// Task timeout helper based on https://devblogs.microsoft.com/pfxteam/crafting-a-task-timeoutafter-method/ - /// - internal static class TaskTimeoutExtensions - { - public static Task WithCancellation(this Task task, CancellationToken cancellationToken) - { - if (task is null) - { - throw new ArgumentNullException(nameof(task)); - } - - if (task.IsCompleted || !cancellationToken.CanBeCanceled) - { - return task; - } - - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - - return WithCancellationCore(task, cancellationToken); - - static async Task WithCancellationCore(Task task, CancellationToken cancellationToken) - { - var tcs = new TaskCompletionSource(); - using CancellationTokenRegistration _ = cancellationToken.UnsafeRegister(static s => ((TaskCompletionSource)s!).TrySetResult(), tcs); - - if (task != await Task.WhenAny(task, tcs.Task).ConfigureAwait(false)) - { - throw new TaskCanceledException(Task.FromCanceled(cancellationToken)); - } - - task.GetAwaiter().GetResult(); // already completed; propagate any exception - } - } - } -} diff --git a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs index bf2ac03377910..69ba465eab5e1 100644 --- a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs +++ b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs @@ -558,9 +558,12 @@ protected async Task WhenAllOrAnyFailed(Task task1, Task task2) } else { - var cts = new CancellationTokenSource(); - await Task.WhenAny(incomplete, Task.Delay(500, cts.Token)); // give second task a chance to complete - cts.Cancel(); + try + { + await incomplete.WaitAsync(TimeSpan.FromMilliseconds(500)); // give second task a chance to complete + } + catch (TimeoutException) { } + await (incomplete.IsCompleted ? Task.WhenAll(completed, incomplete) : completed); } } diff --git a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs index 1ec1835d83a4e..d3095bd7a2045 100644 --- a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs @@ -34,7 +34,7 @@ public Task CreateClientAndServerAsync(Func clientFunc, Func(); @@ -909,7 +908,7 @@ public override async Task WaitForCancellationAsync(bool ignoreIncomingData = tr Frame frame; do { - frame = await ReadFrameAsync(TimeSpan.FromMilliseconds(TestHelper.PassingTestTimeoutMilliseconds)); + frame = await ReadFrameAsync(TestHelper.PassingTestTimeout); Assert.NotNull(frame); // We should get Rst before closing connection. Assert.Equal(0, (int)(frame.Flags & FrameFlags.EndStream)); if (ignoreIncomingData) diff --git a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs index 53757b9ad5671..45c2edf345951 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs @@ -192,7 +192,7 @@ public static async Task CreateServerAsync(Func { using (var server = Http2LoopbackServer.CreateServer()) { - await funcAsync(server, server.Address).TimeoutAfter(millisecondsTimeout).ConfigureAwait(false); + await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout)); } } @@ -223,7 +223,7 @@ public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60000, GenericLoopbackOptions options = null) { using GenericLoopbackServer server = CreateServer(options); - await funcAsync(server, server.Address).TimeoutAfter(millisecondsTimeout).ConfigureAwait(false); + await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout)); } public override Task CreateConnectionAsync(Socket socket, Stream stream, GenericLoopbackOptions options = null) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs index 7e0f4e43838b5..50a6cd6eff7ff 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs @@ -208,7 +208,7 @@ public static async Task CreateServerAsync(Func // Send Digest challenge. Task> serverTask = proxyServer.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.ProxyAuthenticationRequired, authHeader); - if (clientTask == await Task.WhenAny(clientTask, serverTask).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds)) + if (clientTask == await Task.WhenAny(clientTask, serverTask).WaitAsync(TestHelper.PassingTestTimeout)) { // Client task shouldn't have completed successfully; propagate failure. Assert.NotEqual(TaskStatus.RanToCompletion, clientTask.Status); diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index e4d0f4e640e8b..1e3089f328925 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -1513,7 +1513,7 @@ await server.AcceptConnectionAsync(async connection => await connection.ReadRequestDataAsync(readBody: true); } catch { } // Eat errors from client disconnect. - await clientFinished.Task.TimeoutAfter(TimeSpan.FromMinutes(2)); + await clientFinished.Task.WaitAsync(TimeSpan.FromMinutes(2)); }); }); } diff --git a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs index d0f0d368a79f4..352f4e714782a 100644 --- a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs +++ b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs @@ -17,7 +17,9 @@ namespace System.Net.Http.Functional.Tests { public static class TestHelper { + public static TimeSpan PassingTestTimeout => TimeSpan.FromMilliseconds(PassingTestTimeoutMilliseconds); public static int PassingTestTimeoutMilliseconds => 60 * 1000; + public static bool JsonMessageContainsKeyValue(string message, string key, string value) { // Deal with JSON encoding of '\' and '"' in value diff --git a/src/libraries/Common/tests/System/Threading/Tasks/TaskTimeoutExtensions.cs b/src/libraries/Common/tests/System/Threading/Tasks/TaskTimeoutExtensions.cs index a2a6c5e087b27..2efde1fef9ad5 100644 --- a/src/libraries/Common/tests/System/Threading/Tasks/TaskTimeoutExtensions.cs +++ b/src/libraries/Common/tests/System/Threading/Tasks/TaskTimeoutExtensions.cs @@ -3,91 +3,50 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; -/// -/// Task timeout helper based on https://devblogs.microsoft.com/pfxteam/crafting-a-task-timeoutafter-method/ -/// namespace System.Threading.Tasks { public static class TaskTimeoutExtensions { - public static async Task WithCancellation(this Task task, CancellationToken cancellationToken) - { - var tcs = new TaskCompletionSource(); - using (cancellationToken.Register(s => ((TaskCompletionSource)s).TrySetResult(true), tcs)) - { - if (task != await Task.WhenAny(task, tcs.Task).ConfigureAwait(false)) - { - throw new OperationCanceledException(cancellationToken); - } - await task; // already completed; propagate any exception - } - } - - public static Task TimeoutAfter(this Task task, int millisecondsTimeout) - => task.TimeoutAfter(TimeSpan.FromMilliseconds(millisecondsTimeout)); - - public static async Task TimeoutAfter(this Task task, TimeSpan timeout) - { - var cts = new CancellationTokenSource(); + #region WaitAsync polyfills + // Test polyfills when targeting a platform that doesn't have these ConfigureAwait overloads on Task - if (task == await Task.WhenAny(task, Task.Delay(timeout, cts.Token)).ConfigureAwait(false)) - { - cts.Cancel(); - await task.ConfigureAwait(false); - } - else - { - throw new TimeoutException($"Task timed out after {timeout}"); - } - } + public static Task WaitAsync(this Task task, TimeSpan timeout) => + WaitAsync(task, timeout, default); - public static Task TimeoutAfter(this Task task, int millisecondsTimeout) - => task.TimeoutAfter(TimeSpan.FromMilliseconds(millisecondsTimeout)); + public static Task WaitAsync(this Task task, CancellationToken cancellationToken) => + WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken); - public static async Task TimeoutAfter(this Task task, TimeSpan timeout) + public async static Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken) { - var cts = new CancellationTokenSource(); - - if (task == await Task.WhenAny(task, Task.Delay(timeout, cts.Token)).ConfigureAwait(false)) - { - cts.Cancel(); - return await task.ConfigureAwait(false); - } - else + var tcs = new TaskCompletionSource(); + using (new Timer(s => ((TaskCompletionSource)s).TrySetException(new TimeoutException()), tcs, timeout, Timeout.InfiniteTimeSpan)) + using (cancellationToken.Register(s => ((TaskCompletionSource)s).TrySetCanceled(), tcs)) { - throw new TimeoutException($"Task timed out after {timeout}"); + await(await Task.WhenAny(task, tcs.Task).ConfigureAwait(false)).ConfigureAwait(false); } } -#if !NETFRAMEWORK - public static Task TimeoutAfter(this ValueTask task, int millisecondsTimeout) - => task.AsTask().TimeoutAfter(TimeSpan.FromMilliseconds(millisecondsTimeout)); - - public static Task TimeoutAfter(this ValueTask task, TimeSpan timeout) - => task.AsTask().TimeoutAfter(timeout); - - public static Task TimeoutAfter(this ValueTask task, int millisecondsTimeout) - => task.AsTask().TimeoutAfter(TimeSpan.FromMilliseconds(millisecondsTimeout)); + public static Task WaitAsync(this Task task, TimeSpan timeout) => + WaitAsync(task, timeout, default); - public static Task TimeoutAfter(this ValueTask task, TimeSpan timeout) - => task.AsTask().TimeoutAfter(timeout); -#endif + public static Task WaitAsync(this Task task, CancellationToken cancellationToken) => + WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken); - public static async Task WhenAllOrAnyFailed(this Task[] tasks, int millisecondsTimeout) + public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken) { - var cts = new CancellationTokenSource(); - Task task = tasks.WhenAllOrAnyFailed(); - if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout, cts.Token)).ConfigureAwait(false)) + var tcs = new TaskCompletionSource(); + using (new Timer(s => ((TaskCompletionSource)s).TrySetException(new TimeoutException()), tcs, timeout, Timeout.InfiniteTimeSpan)) + using (cancellationToken.Register(s => ((TaskCompletionSource)s).TrySetCanceled(), tcs)) { - cts.Cancel(); - await task.ConfigureAwait(false); - } - else - { - throw new TimeoutException($"{nameof(WhenAllOrAnyFailed)} timed out after {millisecondsTimeout}ms"); + return await (await Task.WhenAny(task, tcs.Task).ConfigureAwait(false)).ConfigureAwait(false); } } + #endregion + + public static async Task WhenAllOrAnyFailed(this Task[] tasks, int millisecondsTimeout) => + await tasks.WhenAllOrAnyFailed().WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout)); public static async Task WhenAllOrAnyFailed(this Task[] tasks) { @@ -99,12 +58,11 @@ public static async Task WhenAllOrAnyFailed(this Task[] tasks) { // Wait a bit to allow other tasks to complete so we can include their exceptions // in the error we throw. - using (var cts = new CancellationTokenSource()) + try { - await Task.WhenAny( - Task.WhenAll(tasks), - Task.Delay(3_000, cts.Token)).ConfigureAwait(false); // arbitrary delay; can be dialed up or down in the future + await Task.WhenAll(tasks).WaitAsync(TimeSpan.FromSeconds(3)); // arbitrary delay; can be dialed up or down in the future } + catch { } var exceptions = new List(); foreach (Task t in tasks) diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs index 75115f3602100..1a8a349eee096 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs @@ -1286,7 +1286,7 @@ void Fail(object state) fileSystemWatcher.CallOnRenamed(new RenamedEventArgs(WatcherChangeTypes.Renamed, root.RootPath, newDirectoryName, oldDirectoryName)); - await Task.WhenAll(oldDirectoryTcs.Task, newDirectoryTcs.Task, newSubDirectoryTcs.Task, newFileTcs.Task).TimeoutAfter(TimeSpan.FromSeconds(30)); + await Task.WhenAll(oldDirectoryTcs.Task, newDirectoryTcs.Task, newSubDirectoryTcs.Task, newFileTcs.Task).WaitAsync(TimeSpan.FromSeconds(30)); Assert.False(oldSubDirectoryToken.HasChanged, "Old subdirectory token should not have changed"); Assert.False(oldFileToken.HasChanged, "Old file token should not have changed"); diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs index 4dd4a4c065714..3be5a0a0e129c 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/IntegrationTesting/src/Deployers/SelfHostDeployer.cs @@ -164,7 +164,7 @@ protected async Task StartSelfHostAsync() // The timeout here is large, because we don't know how long the test could need // We cover a lot of error cases above, but I want to make sure we eventually give up and don't hang the build // just in case we missed one -anurse - await started.Task.TimeoutAfter(TimeSpan.FromMinutes(10)); + await started.Task.WaitAsync(TimeSpan.FromMinutes(10)); } return hostExitTokenSource.Token; diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/ShutdownTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/ShutdownTests.cs index c9a4af01e5bc7..d04ed442a9444 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/ShutdownTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/FunctionalTests/ShutdownTests.cs @@ -96,11 +96,11 @@ private async Task ExecuteShutdownTest(string testName, string shutdownMechanic) } }; - await started.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); + await started.Task.WaitAsync(TimeSpan.FromSeconds(60)); SendShutdownSignal(deployer.HostProcess); - await completed.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); + await completed.Task.WaitAsync(TimeSpan.FromSeconds(60)); WaitForExitOrKill(deployer.HostProcess); diff --git a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.ConcurrentAccessDetection.cs b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.ConcurrentAccessDetection.cs index a2ceab42afcb8..452ab136bf681 100644 --- a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.ConcurrentAccessDetection.cs +++ b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.ConcurrentAccessDetection.cs @@ -34,7 +34,7 @@ private async Task DictionaryConcurrentAccessDetection(Dictionary< }, TaskCreationOptions.LongRunning); // If Dictionary regresses, we do not want to hang here indefinitely - Assert.True((await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(60))) == task) && task.IsCompletedSuccessfully); + await task.WaitAsync(TimeSpan.FromSeconds(60)); } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] diff --git a/src/libraries/System.ComponentModel.EventBasedAsync/tests/BackgroundWorkerTests.cs b/src/libraries/System.ComponentModel.EventBasedAsync/tests/BackgroundWorkerTests.cs index 7bdfb4d6a34df..cb12f5f0ca48f 100644 --- a/src/libraries/System.ComponentModel.EventBasedAsync/tests/BackgroundWorkerTests.cs +++ b/src/libraries/System.ComponentModel.EventBasedAsync/tests/BackgroundWorkerTests.cs @@ -84,8 +84,7 @@ public async Task RunWorkerAsync_NoOnWorkHandler_SetsResultToNull() backgroundWorker.RunWorkerAsync(); - await Task.WhenAny(tcs.Task, Task.Delay(TimeSpan.FromSeconds(10))); // Usually takes 100th of a sec - Assert.True(tcs.Task.IsCompleted); + await tcs.Task.WaitAsync(TimeSpan.FromSeconds(10)); // Usually takes 100th of a sec } #region TestCancelAsync diff --git a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj index d657e211def61..f37055179859c 100644 --- a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj +++ b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj @@ -37,10 +37,6 @@ Link="System\PasteArguments.cs" /> - - diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs index 83640ff93c1b6..7205722a9312e 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs @@ -251,25 +251,7 @@ private bool FlushMessageQueue(bool rethrowInNewThread) } } - // Wait until we hit EOF. This is called from Process.WaitForExit - // We will lose some information if we don't do this. - internal void WaitUntilEOF() - { - if (_readToBufferTask is Task task) - { - task.GetAwaiter().GetResult(); - } - } - - internal Task WaitUntilEOFAsync(CancellationToken cancellationToken) - { - if (_readToBufferTask is Task task) - { - return task.WithCancellation(cancellationToken); - } - - return Task.CompletedTask; - } + internal Task EOF => _readToBufferTask ?? Task.CompletedTask; public void Dispose() { diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs index fb52afebdf2a2..55c5a615a605f 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs @@ -202,14 +202,8 @@ private bool WaitForExitCore(int milliseconds) if (exited && milliseconds == Timeout.Infinite) // if we have a hard timeout, we cannot wait for the streams { - if (_output != null) - { - _output.WaitUntilEOF(); - } - if (_error != null) - { - _error.WaitUntilEOF(); - } + _output?.EOF.GetAwaiter().GetResult(); + _error?.EOF.GetAwaiter().GetResult(); } return exited; diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs index f8da13f762a9d..2a5bd7ed6ae9b 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs @@ -179,11 +179,11 @@ private bool WaitForExitCore(int milliseconds) finally { // If we have a hard timeout, we cannot wait for the streams - if (_output != null && milliseconds == Timeout.Infinite) - _output.WaitUntilEOF(); - - if (_error != null && milliseconds == Timeout.Infinite) - _error.WaitUntilEOF(); + if (milliseconds == Timeout.Infinite) + { + _output?.EOF.GetAwaiter().GetResult(); + _error?.EOF.GetAwaiter().GetResult(); + } handle?.Dispose(); } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs index 9789c2baddb68..6c9181f8655d6 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs @@ -1449,7 +1449,7 @@ public async Task WaitForExitAsync(CancellationToken cancellationToken = default // exception up to the user if (HasExited) { - await WaitUntilOutputEOF().ConfigureAwait(false); + await WaitUntilOutputEOF(cancellationToken).ConfigureAwait(false); return; } @@ -1477,23 +1477,23 @@ public async Task WaitForExitAsync(CancellationToken cancellationToken = default } // Wait until output streams have been drained - await WaitUntilOutputEOF().ConfigureAwait(false); + await WaitUntilOutputEOF(cancellationToken).ConfigureAwait(false); } finally { Exited -= handler; } - async ValueTask WaitUntilOutputEOF() + async Task WaitUntilOutputEOF(CancellationToken cancellationToken) { - if (_output != null) + if (_output is not null) { - await _output.WaitUntilEOFAsync(cancellationToken).ConfigureAwait(false); + await _output.EOF.WaitAsync(cancellationToken).ConfigureAwait(false); } - if (_error != null) + if (_error is not null) { - await _error.WaitUntilEOFAsync(cancellationToken).ConfigureAwait(false); + await _error.EOF.WaitAsync(cancellationToken).ConfigureAwait(false); } } } diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs index 76efea2d3bb54..5178f3a9d5298 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs @@ -199,12 +199,12 @@ public async Task SendAsync_MultipleHttp2ConnectionsEnabled_CreateAdditionalConn aboveLimitRequest.Content = new StringContent($"{payloadText}-{maxActiveStreamsLimit + 1}"); Task aboveLimitResponseTask = client.SendAsync(aboveLimitRequest, HttpCompletionOption.ResponseContentRead); - await aboveLimitResponseTask.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds); + await aboveLimitResponseTask.WaitAsync(TestHelper.PassingTestTimeout); await VerifyResponse(aboveLimitResponseTask, $"{payloadText}-{maxActiveStreamsLimit + 1}"); delaySource.SetResult(true); - await Task.WhenAll(requests.Select(r => r.task).ToArray()).TimeoutAfter(15000); + await Task.WhenAll(requests.Select(r => r.task).ToArray()).WaitAsync(TimeSpan.FromSeconds(15)); foreach ((Task task, DelayedStream stream) in requests) { @@ -212,7 +212,7 @@ public async Task SendAsync_MultipleHttp2ConnectionsEnabled_CreateAdditionalConn HttpResponseMessage response = task.Result; Assert.True(response.IsSuccessStatusCode); Assert.Equal(HttpVersion20.Value, response.Version); - string responsePayload = await response.Content.ReadAsStringAsync().TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds); + string responsePayload = await response.Content.ReadAsStringAsync().WaitAsync(TestHelper.PassingTestTimeout); Assert.Contains(payloadText, responsePayload); } } @@ -245,7 +245,7 @@ private async Task VerifyResponse(Task task, string payload HttpResponseMessage response = task.Result; Assert.True(response.IsSuccessStatusCode); Assert.Equal(HttpVersion20.Value, response.Version); - string responsePayload = await response.Content.ReadAsStringAsync().TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds); + string responsePayload = await response.Content.ReadAsStringAsync().WaitAsync(TestHelper.PassingTestTimeout); Assert.Contains(payloadText, responsePayload); } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs index 12db501f35728..9c85a6fe07a55 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs @@ -416,31 +416,31 @@ public async Task GetAsync_SettingsFrameNotSentOnNewConnection_ClientApplies100S sendTasks.Add(client.GetAsync(server.Address)); } - Http2LoopbackConnection connection = await connectionTask.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + Http2LoopbackConnection connection = await connectionTask.WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Client sets the default MaxConcurrentStreams to 100, so accept 100 requests. - List acceptedRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + List acceptedRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(DefaultMaxConcurrentStreams, acceptedRequests.Count); // Extra request is queued on the client. Task extraSendTask = client.GetAsync(server.Address); - await Assert.ThrowsAnyAsync(() => connection.ReadRequestHeaderAsync()).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Assert.ThrowsAnyAsync(() => connection.ReadRequestHeaderAsync()).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Send SETTINGS frame to increase the default stream limit by 1, unblocking the extra request. await connection.SendSettingsAsync(timeout, new[] { new SettingsEntry() { SettingId = SettingId.MaxConcurrentStreams, Value = DefaultMaxConcurrentStreams + 1 } }).ConfigureAwait(false); - (int extraStreamId, _) = await connection.ReadAndParseRequestHeaderAsync().TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + (int extraStreamId, _) = await connection.ReadAndParseRequestHeaderAsync().WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Respond to all the requests. acceptedRequests.Add(extraStreamId); foreach (int streamId in acceptedRequests) { - await connection.SendDefaultResponseAsync(streamId).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await connection.SendDefaultResponseAsync(streamId).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); } sendTasks.Add(extraSendTask); - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); foreach (Task sendTask in sendTasks) { @@ -468,17 +468,17 @@ public async Task GetAsync_ServerDelaysSendingSettingsThenSetsLowerMaxConcurrent sendTasks.Add(client.GetAsync(server.Address)); } - Http2LoopbackConnection connection = await connectionTask.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + Http2LoopbackConnection connection = await connectionTask.WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Client sets the default MaxConcurrentStreams to 100, so accept 100 requests. - List acceptedRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams + ExtraStreams).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + List acceptedRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams + ExtraStreams).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(DefaultMaxConcurrentStreams, acceptedRequests.Count); // Send SETTINGS frame with MaxConcurrentStreams = 102 await connection.SendSettingsAsync(timeout, new[] { new SettingsEntry() { SettingId = SettingId.MaxConcurrentStreams, Value = DefaultMaxConcurrentStreams + 2 } }).ConfigureAwait(false); // Increased MaxConcurrentStreams ublocks only 2 requests. - List acceptedExtraRequests = await AcceptRequests(connection, ExtraStreams).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + List acceptedExtraRequests = await AcceptRequests(connection, ExtraStreams).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(2, acceptedExtraRequests.Count); acceptedRequests.AddRange(acceptedExtraRequests); @@ -489,7 +489,7 @@ public async Task GetAsync_ServerDelaysSendingSettingsThenSetsLowerMaxConcurrent await connection.WriteFrameAsync(frame).ConfigureAwait(false); // Increased MaxConcurrentStreams ublocks all remaining requests. - acceptedExtraRequests = await AcceptRequests(connection, ExtraStreams - 2).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + acceptedExtraRequests = await AcceptRequests(connection, ExtraStreams - 2).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(ExtraStreams - 2, acceptedExtraRequests.Count); acceptedRequests.AddRange(acceptedExtraRequests); @@ -497,10 +497,10 @@ public async Task GetAsync_ServerDelaysSendingSettingsThenSetsLowerMaxConcurrent // Respond to all the requests. foreach (int streamId in acceptedRequests) { - await connection.SendDefaultResponseAsync(streamId).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await connection.SendDefaultResponseAsync(streamId).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); } - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); foreach (Task sendTask in sendTasks) { @@ -527,15 +527,15 @@ public async Task GetAsync_ServerSendSettingsWithoutMaxConcurrentStreams_ClientA sendTasks.Add(client.GetAsync(server.Address)); } - Http2LoopbackConnection connection = await connectionTask.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + Http2LoopbackConnection connection = await connectionTask.WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Client sets the default MaxConcurrentStreams to 100, so accept 100 requests. - List acceptedRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + List acceptedRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(DefaultMaxConcurrentStreams, acceptedRequests.Count); // Extra request is queued on the client. Task extraSendTask = client.GetAsync(server.Address); - await Assert.ThrowsAnyAsync(() => connection.ReadRequestHeaderAsync()).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Assert.ThrowsAnyAsync(() => connection.ReadRequestHeaderAsync()).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Send SETTINGS frame without MaxConcurrentSettings value. await connection.SendSettingsAsync(timeout, new SettingsEntry[0]).ConfigureAwait(false); @@ -548,18 +548,18 @@ public async Task GetAsync_ServerSendSettingsWithoutMaxConcurrentStreams_ClientA } // Client sets the MaxConcurrentStreams to 'infinite', so accept 100 + 1 extra requests. - List acceptedExtraRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams + 1).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + List acceptedExtraRequests = await AcceptRequests(connection, DefaultMaxConcurrentStreams + 1).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(DefaultMaxConcurrentStreams + 1, acceptedExtraRequests.Count); // Respond to all the requests. acceptedRequests.AddRange(acceptedExtraRequests); foreach (int streamId in acceptedRequests) { - await connection.SendDefaultResponseAsync(streamId).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await connection.SendDefaultResponseAsync(streamId).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); } sendTasks.Add(extraSendTask); - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); foreach (Task sendTask in sendTasks) { @@ -1699,7 +1699,11 @@ await Http2LoopbackServer.CreateClientAndServerAsync( } // Let connection live until server finishes. - await Task.WhenAny(serverFinished.Task, Task.Delay(pingTimeout * 3)); + try + { + await serverFinished.Task.WaitAsync(pingTimeout * 3); + } + catch (TimeoutException) { } }, async server => { @@ -2004,7 +2008,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async url => await Assert.ThrowsAnyAsync(async () => await client.SendAsync(request, cts.Token)); // Wait until the RST_STREAM for the previous request is received before the next request starts. - await rstReceived.Task.TimeoutAfter(TimeSpan.FromSeconds(60)); + await rstReceived.Task.WaitAsync(TimeSpan.FromSeconds(60)); // Send another request to verify that connection is still functional. request = new HttpRequestMessage(HttpMethod.Get, url); @@ -2026,7 +2030,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async url => // Cancel client after receiving Headers or part of request body. cts.Cancel(); } - frame = await connection.ReadFrameAsync(TimeSpan.FromMilliseconds(TestHelper.PassingTestTimeoutMilliseconds)); + frame = await connection.ReadFrameAsync(TestHelper.PassingTestTimeout); Assert.NotNull(frame); // We should get Rst before closing connection. Assert.Equal(0, (int)(frame.Flags & FrameFlags.EndStream)); frameCount++; @@ -2115,7 +2119,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async url => Frame frame; do { - frame = await connection.ReadFrameAsync(TimeSpan.FromMilliseconds(TestHelper.PassingTestTimeoutMilliseconds)); + frame = await connection.ReadFrameAsync(TestHelper.PassingTestTimeout); Assert.NotNull(frame); // We should get Rst before closing connection. Assert.Equal(0, (int)(frame.Flags & FrameFlags.EndStream)); } while (frame.Type != FrameType.RstStream); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs index 5c674714b0b42..230a9a6d40da1 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -132,7 +132,7 @@ public async Task Public_Interop_ExactVersion_Success(string uri) Version = HttpVersion.Version30, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; - using HttpResponseMessage response = await client.SendAsync(request).TimeoutAfter(20_000); + using HttpResponseMessage response = await client.SendAsync(request).WaitAsync(TimeSpan.FromSeconds(20)); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(3, response.Version.Major); @@ -155,7 +155,7 @@ public async Task Public_Interop_Upgrade_Success(string uri) VersionPolicy = HttpVersionPolicy.RequestVersionOrLower }) { - using HttpResponseMessage responseA = await client.SendAsync(requestA).TimeoutAfter(20_000); + using HttpResponseMessage responseA = await client.SendAsync(requestA).WaitAsync(TimeSpan.FromSeconds(20)); Assert.Equal(HttpStatusCode.OK, responseA.StatusCode); Assert.NotEqual(3, responseA.Version.Major); } @@ -170,7 +170,7 @@ public async Task Public_Interop_Upgrade_Success(string uri) VersionPolicy = HttpVersionPolicy.RequestVersionOrLower }) { - using HttpResponseMessage responseB = await client.SendAsync(requestB).TimeoutAfter(20_000); + using HttpResponseMessage responseB = await client.SendAsync(requestB).WaitAsync(TimeSpan.FromSeconds(20)); Assert.Equal(HttpStatusCode.OK, responseB.StatusCode); Assert.NotEqual(3, responseB.Version.Major); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index fdca1908e0f23..a3359f238f9d6 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -66,7 +66,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => GC.WaitForPendingFinalizers(); } - await completedWhenFinalized.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds); + await completedWhenFinalized.WaitAsync(TestHelper.PassingTestTimeout); } } finally @@ -213,7 +213,7 @@ await server.AcceptConnectionAsync(async connection => await request1; // Now the second request should complete. - await secondResponse.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds); + await secondResponse.WaitAsync(TestHelper.PassingTestTimeout); }); }); } @@ -1574,7 +1574,7 @@ await proxyServer.AcceptConnectionAsync(async connection => } } }); - await serverTask.TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds); + await serverTask.WaitAsync(TestHelper.PassingTestTimeout); } } @@ -2065,8 +2065,8 @@ public async Task Http2_MultipleConnectionsEnabled_ConnectionLimitNotReached_Con } } - await Task.WhenAll(responseTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(responseTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); await VerifySendTasks(sendTasks).ConfigureAwait(false); } @@ -2102,7 +2102,7 @@ public async Task Http2_MultipleConnectionsEnabled_InfiniteRequestsCompletelyBlo Assert.Equal(MaxConcurrentStreams, handledRequestCount); - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); await VerifySendTasks(sendTasks).ConfigureAwait(false); } @@ -2131,7 +2131,7 @@ public async Task Http2_MultipleConnectionsEnabled_OpenAndCloseMultipleConnectio HandleAllPendingRequests(connection2, sendTasks.Count) }; - await Task.WhenAll(handleRequestTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(handleRequestTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(handleRequestTasks[0].Result.Count, MaxConcurrentStreams); Assert.Equal(handleRequestTasks[1].Result.Count, MaxConcurrentStreams); @@ -2154,13 +2154,13 @@ public async Task Http2_MultipleConnectionsEnabled_OpenAndCloseMultipleConnectio HandleAllPendingRequests(connection4, sendTasks.Count) }; - await Task.WhenAll(finalHandleTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(finalHandleTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); Assert.Equal(finalHandleTasks[0].Result.Count, MaxConcurrentStreams); Assert.Equal(finalHandleTasks[1].Result.Count, MaxConcurrentStreams); Assert.Equal(finalHandleTasks[2].Result.Count, MaxConcurrentStreams); - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); await VerifySendTasks(sendTasks).ConfigureAwait(false); } @@ -2191,16 +2191,16 @@ public async Task Http2_MultipleConnectionsEnabled_IdleConnectionTimeoutExpired_ Assert.Equal(MaxConcurrentStreams, handledRequests1); // Complete all the requests. - await Task.WhenAll(connection1SendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(connection1SendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); await VerifySendTasks(connection1SendTasks).ConfigureAwait(false); connection1SendTasks.ForEach(t => t.Result.Dispose()); // Wait until the idle connection timeout expires. - await connection1.WaitForClientDisconnectAsync(false).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await connection1.WaitForClientDisconnectAsync(false).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); // Client connection might be still alive, so send an extra request which will either land on the shutting down connection or on a new one. try { - await client.GetAsync(server.Address).TimeoutAfter(handler.PooledConnectionIdleTimeout).ConfigureAwait(false); + await client.GetAsync(server.Address).WaitAsync(handler.PooledConnectionIdleTimeout).ConfigureAwait(false); } catch (Exception) { @@ -2221,7 +2221,7 @@ public async Task Http2_MultipleConnectionsEnabled_IdleConnectionTimeoutExpired_ int handledRequests0 = await SendResponses(connection0, acceptedStreamIds).ConfigureAwait(false); Assert.Equal(MaxConcurrentStreams, handledRequests0); - await Task.WhenAll(sendTasks).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await Task.WhenAll(sendTasks).WaitAsync(TestHelper.PassingTestTimeout).ConfigureAwait(false); await VerifySendTasks(sendTasks).ConfigureAwait(false); } @@ -2247,13 +2247,13 @@ private async Task VerifySendTasks(IReadOnlyList> send private async Task PrepareConnection(Http2LoopbackServer server, HttpClient client, uint maxConcurrentStreams, int readTimeout = 3, int expectedWarmUpTasks = 1) { Task warmUpTask = client.GetAsync(server.Address); - Http2LoopbackConnection connection = await GetConnection(server, maxConcurrentStreams, readTimeout).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds * 2).ConfigureAwait(false); + Http2LoopbackConnection connection = await GetConnection(server, maxConcurrentStreams, readTimeout).WaitAsync(TestHelper.PassingTestTimeout * 2).ConfigureAwait(false); // Wait until the client confirms MaxConcurrentStreams setting took into effect. Task settingAckReceived = connection.SettingAckWaiter; while (true) { Task handleRequestTask = HandleAllPendingRequests(connection, expectedWarmUpTasks); - await Task.WhenAll(warmUpTask, handleRequestTask).TimeoutAfter(TestHelper.PassingTestTimeoutMilliseconds * 2).ConfigureAwait(false); + await Task.WhenAll(warmUpTask, handleRequestTask).WaitAsync(TestHelper.PassingTestTimeout * 2).ConfigureAwait(false); Assert.True(warmUpTask.Result.IsSuccessStatusCode); warmUpTask.Result.Dispose(); if (settingAckReceived.IsCompleted) diff --git a/src/libraries/System.Net.HttpListener/tests/HttpListenerTests.cs b/src/libraries/System.Net.HttpListener/tests/HttpListenerTests.cs index c4ec07664961c..e781dcbcd2419 100644 --- a/src/libraries/System.Net.HttpListener/tests/HttpListenerTests.cs +++ b/src/libraries/System.Net.HttpListener/tests/HttpListenerTests.cs @@ -165,10 +165,10 @@ public async Task GetContext_StopIsCalled_GetContextUnblocked() var listener = listenerFactory.GetListener(); listener.Start(); var listenerTask = Task.Run(() => Assert.Throws(() => listener.GetContext())); - await Task.Delay(1000).TimeoutAfter(10000); // Wait for listenerTask to call GetContext. + await Task.Delay(1000); // Wait for listenerTask to call GetContext. listener.Stop(); listener.Close(); - await listenerTask.TimeoutAfter(10000); + await listenerTask.WaitAsync(TimeSpan.FromSeconds(10)); } } } diff --git a/src/libraries/System.Net.HttpListener/tests/HttpRequestStreamTests.cs b/src/libraries/System.Net.HttpListener/tests/HttpRequestStreamTests.cs index ba1f6b5892f9b..233f3edaca06e 100644 --- a/src/libraries/System.Net.HttpListener/tests/HttpRequestStreamTests.cs +++ b/src/libraries/System.Net.HttpListener/tests/HttpRequestStreamTests.cs @@ -45,7 +45,7 @@ private async Task ReadLengthAsync(Stream stream, byte[] array, int offset, do { - readLength = await TaskTimeoutExtensions.TimeoutAfter(stream.ReadAsync(array, offset, remaining), TimeoutMilliseconds); + readLength = await stream.ReadAsync(array, offset, remaining).WaitAsync(TimeSpan.FromMilliseconds(TimeoutMilliseconds)); if (readLength <= 0) { break; diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs index 9519ff7529f41..45ab7b583e387 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs @@ -349,7 +349,7 @@ public async Task TestMailDeliveryAsync(string body) using SmtpClient client = server.CreateClient(); MailMessage msg = new MailMessage("foo@example.com", "bar@example.com", "hello", body); - await client.SendMailAsync(msg).TimeoutAfter((int)TimeSpan.FromSeconds(30).TotalMilliseconds); + await client.SendMailAsync(msg).WaitAsync(TimeSpan.FromSeconds(30)); Assert.Equal("", server.MailFrom); Assert.Equal("", server.MailTo); @@ -510,7 +510,7 @@ public async Task SendMail_SendQUITOnDispose(bool asyncSend) MailMessage msg = new MailMessage("foo@example.com", "bar@example.com", "hello", "howdydoo"); if (asyncSend) { - await client.SendMailAsync(msg).TimeoutAfter((int)TimeSpan.FromSeconds(30).TotalMilliseconds); + await client.SendMailAsync(msg).WaitAsync(TimeSpan.FromSeconds(30)); } else { diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs index 3f0bbbc7b9170..4f87263a9b248 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs @@ -251,10 +251,11 @@ await socket.SendToAsync( SocketFlags.None, socketConfig.EndPoint); - var cts = new CancellationTokenSource(); - Task finished = await Task.WhenAny(receiveTask, Task.Delay(timeout - (int)elapsed, cts.Token)).ConfigureAwait(false); - cts.Cancel(); - if (finished != receiveTask) + try + { + await receiveTask.WaitAsync(TimeSpan.FromMilliseconds(timeout - (int)elapsed)).ConfigureAwait(false); + } + catch (TimeoutException) { return CreateTimedOutPingReply(); } @@ -332,34 +333,31 @@ private async Task SendWithPingUtilityAsync(IPAddress address, byte[] p.Exited += (s, e) => processCompletion.SetResult(); p.Start(); - var cts = new CancellationTokenSource(); - Task timeoutTask = Task.Delay(timeout, cts.Token); - Task finished = await Task.WhenAny(processCompletion.Task, timeoutTask).ConfigureAwait(false); - - if (finished == timeoutTask) + try + { + await processCompletion.Task.WaitAsync(TimeSpan.FromMilliseconds(timeout)).ConfigureAwait(false); + } + catch (TimeoutException) { p.Kill(); return CreateTimedOutPingReply(); } - else + + if (p.ExitCode == 1 || p.ExitCode == 2) { - cts.Cancel(); - if (p.ExitCode == 1 || p.ExitCode == 2) - { - // Throw timeout for known failure return codes from ping functions. - return CreateTimedOutPingReply(); - } + // Throw timeout for known failure return codes from ping functions. + return CreateTimedOutPingReply(); + } - try - { - string output = await p.StandardOutput.ReadToEndAsync().ConfigureAwait(false); - return ParsePingUtilityOutput(address, output); - } - catch (Exception) - { - // If the standard output cannot be successfully parsed, throw a generic PingException. - throw new PingException(SR.net_ping); - } + try + { + string output = await p.StandardOutput.ReadToEndAsync().ConfigureAwait(false); + return ParsePingUtilityOutput(address, output); + } + catch (Exception) + { + // If the standard output cannot be successfully parsed, throw a generic PingException. + throw new PingException(SR.net_ping); } } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index 39d2eebc668b8..8ad870ad82bea 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -79,7 +79,7 @@ public async Task SetListenerTimeoutWorksWithSmallTimeout() using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); await clientTask; - await Assert.ThrowsAsync(async () => await serverConnection.AcceptStreamAsync().TimeoutAfter(100000)); + await Assert.ThrowsAsync(async () => await serverConnection.AcceptStreamAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(100))); } [Theory] diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 3fbfcaf75c653..a54c9fbe1cc7a 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -25,7 +25,7 @@ await Task.Run(async () => using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); await clientStreamTask; - }).TimeoutAfter(millisecondsTimeout: 6_000); + }).WaitAsync(TimeSpan.FromSeconds(6)); } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs index f3c15174652f6..01cf73a6bc316 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -508,7 +508,7 @@ await Task.Run(async () => byte[] buffer = new byte[100]; QuicStreamAbortedException ex = await Assert.ThrowsAsync(() => serverStream.ReadAsync(buffer).AsTask()); Assert.Equal(ExpectedErrorCode, ex.ErrorCode); - }).TimeoutAfter(millisecondsTimeout: 5_000); + }).WaitAsync(TimeSpan.FromSeconds(5)); } [ActiveIssue("https://github.com/dotnet/runtime/issues/32050")] @@ -538,7 +538,7 @@ await Task.Run(async () => byte[] buffer = new byte[100]; QuicConnectionAbortedException ex = await Assert.ThrowsAsync(() => serverStream.ReadAsync(buffer).AsTask()); Assert.Equal(ExpectedErrorCode, ex.ErrorCode); - }).TimeoutAfter(millisecondsTimeout: 5_000); + }).WaitAsync(TimeSpan.FromSeconds(5)); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs index 8ef2e170b69e8..50dd158345ff7 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs @@ -152,7 +152,7 @@ private async Task ClientAsyncSslHelper( using (SslStream sslStream = new SslStream(client.GetStream(), false, certificateCallback != null ? certificateCallback : AllowAnyServerCertificate, null)) { Task clientAuthTask = sslStream.AuthenticateAsClientAsync(serverName, null, clientSslProtocols, false); - await clientAuthTask.TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await clientAuthTask.WaitAsync(TestConfiguration.PassingTestTimeout); _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", server.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs index cbff02a3c94ff..8ca45a58f4638 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs @@ -177,7 +177,7 @@ public async Task NegotiateStream_ServerAuthenticationRemote_Success() string clientName = Configuration.Security.NegotiateClient.Host; int clientPort = Configuration.Security.NegotiateClient.Port; await controlClient.ConnectAsync(clientName, clientPort) - .TimeoutAfter(TimeSpan.FromSeconds(15)); + .WaitAsync(TimeSpan.FromSeconds(15)); var serverStream = controlClient.GetStream(); using (var serverAuth = new NegotiateStream(serverStream, leaveInnerStreamOpen: false)) @@ -186,7 +186,7 @@ await serverAuth.AuthenticateAsServerAsync( CredentialCache.DefaultNetworkCredentials, ProtectionLevel.EncryptAndSign, TokenImpersonationLevel.Identification) - .TimeoutAfter(TimeSpan.FromSeconds(15)); + .WaitAsync(TimeSpan.FromSeconds(15)); Assert.True(serverAuth.IsAuthenticated, "IsAuthenticated"); Assert.True(serverAuth.IsEncrypted, "IsEncrypted"); @@ -200,7 +200,7 @@ await serverAuth.AuthenticateAsServerAsync( var message = "Hello from the client."; using (var reader = new StreamReader(serverAuth)) { - var response = await reader.ReadToEndAsync().TimeoutAfter(TimeSpan.FromSeconds(15)); + var response = await reader.ReadToEndAsync().WaitAsync(TimeSpan.FromSeconds(15)); Assert.Equal(message, response); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs index 4307b3df9d275..73d480a304858 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs @@ -384,7 +384,7 @@ private async Task ServerAsyncSslHelper( try { - await clientAuthentication.TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await clientAuthentication.WaitAsync(TestConfiguration.PassingTestTimeout); _logVerbose.WriteLine("ServerAsyncAuthenticateTest.clientAuthentication complete."); } catch (Exception ex) @@ -394,7 +394,7 @@ private async Task ServerAsyncSslHelper( clientStream.Socket.Shutdown(SocketShutdown.Send); } - await serverAuthentication.TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await serverAuthentication.WaitAsync(TestConfiguration.PassingTestTimeout); _logVerbose.WriteLine("ServerAsyncAuthenticateTest.serverAuthentication complete."); _log.WriteLine( diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlertsTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlertsTest.cs index e11de123b5d83..7c57a62858fe2 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlertsTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlertsTest.cs @@ -29,16 +29,14 @@ public async Task SslStream_StreamToStream_HandshakeAlert_Ok() using (var server = new SslStream(stream2, true, FailClientCertificate)) using (X509Certificate2 certificate = Configuration.Certificates.GetServerCertificate()) { - int timeout = TestConfiguration.PassingTestTimeoutMilliseconds; - Task serverAuth = server.AuthenticateAsServerAsync(certificate); - await client.AuthenticateAsClientAsync(certificate.GetNameInfo(X509NameType.SimpleName, false)).TimeoutAfter(timeout); + await client.AuthenticateAsClientAsync(certificate.GetNameInfo(X509NameType.SimpleName, false)).WaitAsync(TestConfiguration.PassingTestTimeout); byte[] buffer = new byte[1024]; // Schannel semantics require that Decrypt is called to receive an alert. await client.WriteAsync(buffer, 0, buffer.Length); - var exception = await Assert.ThrowsAsync(() => client.ReadAsync(buffer, 0, buffer.Length)).TimeoutAfter(timeout); + var exception = await Assert.ThrowsAsync(() => client.ReadAsync(buffer, 0, buffer.Length)).WaitAsync(TestConfiguration.PassingTestTimeout); Assert.IsType(exception.InnerException); var win32ex = (Win32Exception)exception.InnerException; @@ -47,7 +45,7 @@ public async Task SslStream_StreamToStream_HandshakeAlert_Ok() // https://msdn.microsoft.com/en-us/library/windows/desktop/dd721886(v=vs.85).aspx Assert.Equal(SEC_E_CERT_UNKNOWN, unchecked((uint)win32ex.NativeErrorCode)); - await Assert.ThrowsAsync(() => serverAuth).TimeoutAfter(timeout); + await Assert.ThrowsAsync(() => serverAuth).WaitAsync(TestConfiguration.PassingTestTimeout); await Assert.ThrowsAsync(() => server.WriteAsync(buffer, 0, buffer.Length)); await Assert.ThrowsAsync(() => server.ReadAsync(buffer, 0, buffer.Length)); @@ -67,7 +65,7 @@ public async Task SslStream_StreamToStream_ServerInitiatedCloseNotify_Ok() handshake[0] = server.AuthenticateAsServerAsync(certificate); handshake[1] = client.AuthenticateAsClientAsync(certificate.GetNameInfo(X509NameType.SimpleName, false)); - await Task.WhenAll(handshake).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(handshake).WaitAsync(TestConfiguration.PassingTestTimeout); var readBuffer = new byte[1024]; @@ -100,7 +98,7 @@ public async Task SslStream_StreamToStream_ClientInitiatedCloseNotify_Ok(bool se handshake[0] = server.AuthenticateAsServerAsync(certificate); handshake[1] = client.AuthenticateAsClientAsync(certificate.GetNameInfo(X509NameType.SimpleName, false)); - await Task.WhenAll(handshake).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(handshake).WaitAsync(TestConfiguration.PassingTestTimeout); var readBuffer = new byte[1024]; @@ -110,7 +108,7 @@ public async Task SslStream_StreamToStream_ClientInitiatedCloseNotify_Ok(bool se // Send some data before shutting down. This may matter for TLS13. handshake[0] = server.WriteAsync(readBuffer, 0, 1); handshake[1] = client.ReadAsync(readBuffer, 0, 1); - await Task.WhenAll(handshake).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(handshake).WaitAsync(TestConfiguration.PassingTestTimeout); } await client.ShutdownAsync(); @@ -137,7 +135,7 @@ public async Task SslStream_StreamToStream_DataAfterShutdown_Fail() handshake[0] = server.AuthenticateAsServerAsync(certificate); handshake[1] = client.AuthenticateAsClientAsync(certificate.GetNameInfo(X509NameType.SimpleName, false)); - await Task.WhenAll(handshake).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(handshake).WaitAsync(TestConfiguration.PassingTestTimeout); var buffer = new byte[1024]; diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs index 5e142982c7c68..fb4fb9d528d0e 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamAlpnTests.cs @@ -158,7 +158,7 @@ public async Task SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail() await Assert.ThrowsAsync(() => serverStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions)); serverStream.Dispose(); - await t1.TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await t1.WaitAsync(TestConfiguration.PassingTestTimeout); } else { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamCredentialCacheTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamCredentialCacheTest.cs index 06b4520055cd9..e2e8314249d36 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamCredentialCacheTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamCredentialCacheTest.cs @@ -36,7 +36,7 @@ public async Task SslStream_SameCertUsedForClientAndServer_Ok() clientCertificateCollection, false); - await Task.WhenAll(tasks).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(tasks).WaitAsync(TestConfiguration.PassingTestTimeout); if (!PlatformDetection.IsWindows7 || Capability.IsTrustedRootCertificateInstalled()) diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamEKUTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamEKUTest.cs index e9c47fc988e98..b49c99868bab8 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamEKUTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamEKUTest.cs @@ -46,7 +46,7 @@ public async Task SslStream_NoEKUServerAuth_Ok() tasks[0] = server.AcceptHttpsClientAsync(); tasks[1] = client.HttpsRequestAsync(); - await Task.WhenAll(tasks).TimeoutAfter(TestTimeoutMilliseconds); + await Task.WhenAll(tasks).WaitAsync(TimeSpan.FromMilliseconds(TestTimeoutMilliseconds)); } } @@ -94,7 +94,7 @@ public async Task SslStream_NoEKUClientAuth_Ok() tasks[0] = server.AcceptHttpsClientAsync(); tasks[1] = client.HttpsRequestAsync(); - await Task.WhenAll(tasks).TimeoutAfter(TestTimeoutMilliseconds); + await Task.WhenAll(tasks).WaitAsync(TimeSpan.FromMilliseconds(TestTimeoutMilliseconds)); } } @@ -156,7 +156,7 @@ public async Task SslStream_SelfSignedClientEKUClientAuth_Ok() tasks[0] = server.AcceptHttpsClientAsync(); tasks[1] = client.HttpsRequestAsync(); - await Task.WhenAll(tasks).TimeoutAfter(TestTimeoutMilliseconds); + await Task.WhenAll(tasks).WaitAsync(TimeSpan.FromMilliseconds(TestTimeoutMilliseconds)); } } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs index efb82869e96d5..5b1e1c7bd146c 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNegotiatedCipherSuiteTest.cs @@ -639,8 +639,8 @@ private static async Task WaitForSecureConnection(SslStream client, S try { - task = await Task.WhenAny(serverTask, clientTask).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds).ConfigureAwait(false); - await task ; + task = await Task.WhenAny(serverTask, clientTask).WaitAsync(TestConfiguration.PassingTestTimeout); + await task; } catch (Exception e) when (e is AuthenticationException || e is Win32Exception) { @@ -660,7 +660,7 @@ private static async Task WaitForSecureConnection(SslStream client, S { // Now wait for the other task to finish. task = (task == serverTask ? clientTask : serverTask); - await task.TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds).ConfigureAwait(false); + await task.WaitAsync(TestConfiguration.PassingTestTimeout); // Fail if server has failed but client has succeeded Assert.Null(failure); diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs index de506cd5ee1f6..ea1e5c5ac35f7 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs @@ -407,7 +407,7 @@ public async Task SslStream_ClientCertificate_SendsChain() Task t1 = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); Task t2 = server.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); - await Task.WhenAll(t1, t2).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(t1, t2).WaitAsync(TestConfiguration.PassingTestTimeout); // hold to the streams so they stay in credential cache streams.Add(client); diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSchSendAuxRecordTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSchSendAuxRecordTest.cs index 6e70e6150b107..2389188bbef5e 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSchSendAuxRecordTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSchSendAuxRecordTest.cs @@ -108,7 +108,7 @@ public async Task SslStream_ClientAndServerUsesAuxRecord_Ok() return Task.FromResult(null); }); - await Task.WhenAll(tasks).TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + await Task.WhenAll(tasks).WaitAsync(TestConfiguration.PassingTestTimeout); if (serverAuxRecordDetectedInconclusive || clientAuxRecordDetectedInconclusive) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs index a563fb18a1ac8..f7ca5892fc052 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs @@ -242,7 +242,7 @@ public async Task SslStream_StreamToStream_Dispose_Throws() var serverBuffer = new byte[1]; Task serverReadTask = ReadAsync(serverSslStream, serverBuffer, 0, serverBuffer.Length); await WriteAsync(serverSslStream, new byte[] { 1 }, 0, 1) - .TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds); + .WaitAsync(TestConfiguration.PassingTestTimeout); // Shouldn't throw, the context is disposed now. // Since the server read task is in progress, the read buffer is not returned to ArrayPool. diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs index 2f4f5d741e4b9..ecfba44a860a4 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs @@ -14,6 +14,7 @@ namespace System.Net.Security.Tests internal static class TestConfiguration { public const int PassingTestTimeoutMilliseconds = 4 * 60 * 1000; + public static TimeSpan PassingTestTimeout => TimeSpan.FromMilliseconds(PassingTestTimeoutMilliseconds); public const string Realm = "TEST.COREFX.NET"; public const string KerberosUser = "krb_user"; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Accept.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Accept.cs index 5eb3fc8c617f3..79756096973be 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Accept.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Accept.cs @@ -318,7 +318,7 @@ await RetryHelper.ExecuteAsync(async () => msDelay *= 2; Task disposeTask = Task.Run(() => listener.Dispose()); - await Task.WhenAny(disposeTask, acceptTask).TimeoutAfter(30000); + await Task.WhenAny(disposeTask, acceptTask).WaitAsync(TimeSpan.FromSeconds(30)); await disposeTask; SocketError? localSocketError = null; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs index c3c20fdf47ad6..67720af567ac8 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs @@ -150,7 +150,7 @@ await RetryHelper.ExecuteAsync(async () => msDelay *= 2; Task disposeTask = Task.Run(() => client.Dispose()); - await Task.WhenAny(disposeTask, connectTask).TimeoutAfter(30000); + await Task.WhenAny(disposeTask, connectTask).WaitAsync(TimeSpan.FromSeconds(30)); await disposeTask; SocketError? localSocketError = null; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveFrom.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveFrom.cs index 854f46b7c9561..f35808386faae 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveFrom.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveFrom.cs @@ -206,12 +206,12 @@ async Task RunTestAsync() if (DisposeDuringOperationResultsInDisposedException) { await Assert.ThrowsAsync(() => receiveTask) - .TimeoutAfter(CancellationTestTimeout); + .WaitAsync(CancellationTestTimeout); } else { SocketException ex = await Assert.ThrowsAsync(() => receiveTask) - .TimeoutAfter(CancellationTestTimeout); + .WaitAsync(CancellationTestTimeout); SocketError expectedError = UsesSync ? SocketError.Interrupted : SocketError.OperationAborted; Assert.Equal(expectedError, ex.SocketErrorCode); } @@ -233,7 +233,7 @@ public async Task ShutdownReceiveBeforeOperation_ThrowsSocketException(SocketShu if (shutdown == SocketShutdown.Both) await Task.Delay(50); SocketException exception = await Assert.ThrowsAnyAsync(() => ReceiveFromAsync(socket, new byte[1], GetGetDummyTestEndpoint())) - .TimeoutAfter(CancellationTestTimeout); + .WaitAsync(CancellationTestTimeout); Assert.Equal(SocketError.Shutdown, exception.SocketErrorCode); } @@ -359,7 +359,7 @@ public async Task WhenCanceled_Throws(IPAddress loopback, bool precanceled) OperationCanceledException ex = await Assert.ThrowsAnyAsync( () => socket.ReceiveFromAsync(buffer, SocketFlags.None, dummy.LocalEndPoint, cts.Token).AsTask()) - .TimeoutAfter(CancellationTestTimeout); + .WaitAsync(CancellationTestTimeout); Assert.Equal(cts.Token, ex.CancellationToken); } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs index d60324847f3ab..eca9145414d1e 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs @@ -209,13 +209,11 @@ async Task RunTestAsync() if (DisposeDuringOperationResultsInDisposedException) { - await Assert.ThrowsAsync(() => receiveTask) - .TimeoutAfter(CancellationTestTimeout); + await Assert.ThrowsAsync(() => receiveTask).WaitAsync(CancellationTestTimeout); } else { - SocketException ex = await Assert.ThrowsAsync(() => receiveTask) - .TimeoutAfter(CancellationTestTimeout); + SocketException ex = await Assert.ThrowsAsync(() => receiveTask).WaitAsync(CancellationTestTimeout); SocketError expectedError = UsesSync ? SocketError.Interrupted : SocketError.OperationAborted; Assert.Equal(expectedError, ex.SocketErrorCode); } @@ -237,7 +235,7 @@ public async Task ShutdownReceiveBeforeOperation_ThrowsSocketException(SocketShu if (shutdown == SocketShutdown.Both) await Task.Delay(50); SocketException exception = await Assert.ThrowsAnyAsync(() => ReceiveMessageFromAsync(socket, new byte[1], GetGetDummyTestEndpoint())) - .TimeoutAfter(CancellationTestTimeout); + .WaitAsync(CancellationTestTimeout); Assert.Equal(SocketError.Shutdown, exception.SocketErrorCode); } @@ -370,7 +368,7 @@ public async Task WhenCanceled_Throws(IPAddress loopback, bool precanceled) OperationCanceledException ex = await Assert.ThrowsAnyAsync( () => socket.ReceiveMessageFromAsync(buffer, SocketFlags.None, dummy.LocalEndPoint, cts.Token).AsTask()) - .TimeoutAfter(CancellationTestTimeout); + .WaitAsync(CancellationTestTimeout); Assert.Equal(cts.Token, ex.CancellationToken); } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SelectTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SelectTest.cs index 6e7c33b84dae5..3f3dd22492b9f 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SelectTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SelectTest.cs @@ -298,7 +298,7 @@ public static async Task Select_AcceptNonBlocking_Success() } // Give the task 5 seconds to complete; if not, assume it's hung. - await t.TimeoutAfter(5000); + await t.WaitAsync(TimeSpan.FromSeconds(5)); } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs index 651c6c54be403..c22b0bcca7135 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs @@ -163,7 +163,7 @@ public async Task IncludeFile_Success(IPAddress listenAt, bool sendPreAndPostBuf client.Shutdown(SocketShutdown.Send); } - await serverTask.TimeoutAfter(TestTimeout); + await serverTask.WaitAsync(TimeSpan.FromMilliseconds(TestTimeout)); Assert.Equal(bytesToSend, bytesReceived); Assert.Equal(sentChecksum.Sum, receivedChecksum.Sum); } @@ -304,7 +304,7 @@ await RetryHelper.ExecuteAsync(async () => msDelay *= 2; Task disposeTask = Task.Run(() => socket1.Dispose()); - await Task.WhenAny(disposeTask, socketOperation).TimeoutAfter(30000); + await Task.WhenAny(disposeTask, socketOperation).WaitAsync(TimeSpan.FromSeconds(30)); await disposeTask; SocketError? localSocketError = null; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceive.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceive.cs index a96680a9eedd7..3d37cc502aeef 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceive.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceive.cs @@ -882,7 +882,7 @@ await RetryHelper.ExecuteAsync(async () => msDelay *= 2; Task disposeTask = Task.Run(() => socket.Dispose()); - await Task.WhenAny(disposeTask, receiveTask).TimeoutAfter(30000); + await Task.WhenAny(disposeTask, receiveTask).WaitAsync(TimeSpan.FromSeconds(30)); await disposeTask; SocketError? localSocketError = null; @@ -966,7 +966,7 @@ await RetryHelper.ExecuteAsync(async () => msDelay *= 2; Task disposeTask = Task.Run(() => socket1.Dispose()); - await Task.WhenAny(disposeTask, socketOperation).TimeoutAfter(30000); + await Task.WhenAny(disposeTask, socketOperation).WaitAsync(TimeSpan.FromSeconds(30)); await disposeTask; SocketError? localSocketError = null; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceiveMisc.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceiveMisc.cs index 4fa40e5d7e9c6..f9fcfcac88626 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceiveMisc.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceiveMisc.cs @@ -177,11 +177,12 @@ public async Task ReceiveIovMaxUdp_SuccessOrMessageSize() { int bytesSent = sender.Send(sendBuffer); Assert.Equal(SegmentCount, bytesSent); - await Task.WhenAny(receiveTask, Task.Delay(3)); - if (receiveTask.IsCompleted) + try { + await receiveTask.WaitAsync(TimeSpan.FromMilliseconds(3)); break; } + catch (TimeoutException) { } } } @@ -249,7 +250,7 @@ public async Task Socket_ReceiveFlags_Success() args.SocketFlags = SocketFlags.Peek; if (receiver.ReceiveAsync(args)) { - await tcs.Task.TimeoutAfter(TestSettings.PassingTestTimeout); + await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(TestSettings.PassingTestTimeout)); } Assert.Equal(SocketFlags.None, args.SocketFlags); Assert.Equal(1, receiveBufer[0]); @@ -261,7 +262,7 @@ public async Task Socket_ReceiveFlags_Success() args.SocketFlags = SocketFlags.None; if (receiver.ReceiveAsync(args)) { - await tcs.Task.TimeoutAfter(TestSettings.PassingTestTimeout); + await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(TestSettings.PassingTestTimeout)); } Assert.Equal(SocketFlags.None, args.SocketFlags); Assert.Equal(1, receiveBufer[0]); @@ -273,7 +274,7 @@ public async Task Socket_ReceiveFlags_Success() args.SetBuffer(receiveBufer, 0, 100); if (receiver.ReceiveAsync(args)) { - await tcs.Task.TimeoutAfter(TestSettings.PassingTestTimeout); + await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(TestSettings.PassingTestTimeout)); } Assert.Equal(SocketFlags.Truncated, args.SocketFlags); Assert.Equal(2, receiveBufer[0]); diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs index dee8dd3ca7359..c36e8c714cbc3 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs @@ -102,11 +102,7 @@ private async Task MulticastInterface_Set_Helper(int interfaceIndex) sendSocket.SendTo(Encoding.UTF8.GetBytes(message), new IPEndPoint(multicastAddress, port)); - var cts = new CancellationTokenSource(); - Assert.True(await Task.WhenAny(receiveTask, Task.Delay(30_000, cts.Token)) == receiveTask, "Waiting for received data timed out"); - cts.Cancel(); - - int bytesReceived = await receiveTask; + int bytesReceived = await receiveTask.WaitAsync(TimeSpan.FromSeconds(30)); string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, bytesReceived); Assert.Equal(receivedMessage, message); @@ -212,11 +208,7 @@ private async Task MulticastInterface_Set_IPv6_Helper(int interfaceIndex) sendSocket.SendTo(Encoding.UTF8.GetBytes(message), new IPEndPoint(multicastAddress, port)); - var cts = new CancellationTokenSource(); - Assert.True(await Task.WhenAny(receiveTask, Task.Delay(30_000, cts.Token)) == receiveTask, "Waiting for received data timed out"); - cts.Cancel(); - - int bytesReceived = await receiveTask; + int bytesReceived = await receiveTask.WaitAsync(TimeSpan.FromSeconds(30)); string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, bytesReceived); Assert.Equal(receivedMessage, message); diff --git a/src/libraries/System.Net.WebClient/tests/WebClientTest.cs b/src/libraries/System.Net.WebClient/tests/WebClientTest.cs index f168d4a9eb071..571aefc3d6815 100644 --- a/src/libraries/System.Net.WebClient/tests/WebClientTest.cs +++ b/src/libraries/System.Net.WebClient/tests/WebClientTest.cs @@ -544,7 +544,7 @@ await LoopbackServer.CreateServerAsync(async (server, url) => if (IsAsync) { - await downloadProgressInvoked.Task.TimeoutAfter(TimeoutMilliseconds); + await downloadProgressInvoked.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeoutMilliseconds)); } }); } @@ -572,7 +572,7 @@ await LoopbackServer.CreateServerAsync(async (server, url) => if (IsAsync) { - await downloadProgressInvokedWithContentLength.Task.TimeoutAfter(TimeoutMilliseconds); + await downloadProgressInvokedWithContentLength.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeoutMilliseconds)); } }); } @@ -643,7 +643,7 @@ public async Task UploadData_Success(Uri server) byte[] ignored = await UploadDataAsync(wc, server.ToString(), Encoding.UTF8.GetBytes(ExpectedText)); if (IsAsync) { - await uploadProgressInvoked.Task.TimeoutAfter(TimeoutMilliseconds); + await uploadProgressInvoked.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeoutMilliseconds)); } } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs index 5e8a1adb5547e..430c324f40ae5 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs @@ -406,7 +406,7 @@ public async Task SendReceive_ConnectionClosedPrematurely_ReceiveAsyncFailsAndWe Assert.NotNull(await LoopbackHelper.WebSocketHandshakeAsync(connection)); // Wait for client-side ConnectAsync to complete and for a pending ReceiveAsync to be posted. - await pendingReceiveAsyncPosted.Task.TimeoutAfter(TimeOutMilliseconds); + await pendingReceiveAsyncPosted.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeOutMilliseconds)); // Close the underlying connection prematurely (without sending a WebSocket Close frame). connection.Socket.Shutdown(SocketShutdown.Both); @@ -424,7 +424,7 @@ public async Task SendReceive_ConnectionClosedPrematurely_ReceiveAsyncFailsAndWe pendingReceiveAsyncPosted.SetResult(); // Wait for the server to close the underlying connection. - await acceptTask.WithCancellation(cts.Token); + await acceptTask.WaitAsync(cts.Token); WebSocketException pendingReceiveException = await Assert.ThrowsAsync(() => pendingReceiveAsync); diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index f6338d7c04cc8..2278e4046c6de 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -3262,8 +3262,8 @@ The specified TaskContinuationOptions excluded all continuation kinds. - - The value needs to translate in milliseconds to -1 (signifying an infinite timeout), 0 or a positive integer less than or equal to the maximum allowed timer duration. + + The value needs to translate in milliseconds to -1 (signifying an infinite timeout), 0, or a positive integer less than or equal to the maximum allowed timer duration. The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs index b51a51269f8d9..f468d0bc7a8f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs @@ -534,6 +534,47 @@ internal override void InnerInvoke() #endregion + #region WaitAsync methods + /// Gets a that will complete when this completes or when the specified has cancellation requested. + /// The to monitor for a cancellation request. + /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. + public new Task WaitAsync(CancellationToken cancellationToken) => + WaitAsync(Timeout.UnsignedInfinite, cancellationToken); + + /// Gets a that will complete when this completes or when the specified timeout expires. + /// The timeout after which the should be faulted with a if it hasn't otherwise completed. + /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. + public new Task WaitAsync(TimeSpan timeout) => + WaitAsync(ValidateTimeout(timeout, ExceptionArgument.timeout), default); + + /// Gets a that will complete when this completes, when the specified timeout expires, or when the specified has cancellation requested. + /// The timeout after which the should be faulted with a if it hasn't otherwise completed. + /// The to monitor for a cancellation request. + /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. + public new Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken) => + WaitAsync(ValidateTimeout(timeout, ExceptionArgument.timeout), cancellationToken); + + private Task WaitAsync(uint millisecondsTimeout, CancellationToken cancellationToken) + { + if (IsCompleted || (!cancellationToken.CanBeCanceled && millisecondsTimeout == Timeout.UnsignedInfinite)) + { + return this; + } + + if (cancellationToken.IsCancellationRequested) + { + return FromCanceled(cancellationToken); + } + + if (millisecondsTimeout == 0) + { + return FromException(new TimeoutException()); + } + + return new CancellationPromise(this, millisecondsTimeout, cancellationToken); + } + #endregion + #region Continuation methods #region Action> continuations 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 8f396bc7c8055..a487e57183696 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 @@ -2732,6 +2732,121 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) return true; } + /// Gets a that will complete when this completes or when the specified has cancellation requested. + /// The to monitor for a cancellation request. + /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. + public Task WaitAsync(CancellationToken cancellationToken) => WaitAsync(Timeout.UnsignedInfinite, cancellationToken); + + /// Gets a that will complete when this completes or when the specified timeout expires. + /// The timeout after which the should be faulted with a if it hasn't otherwise completed. + /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. + public Task WaitAsync(TimeSpan timeout) => WaitAsync(ValidateTimeout(timeout, ExceptionArgument.timeout), default); + + /// Gets a that will complete when this completes, when the specified timeout expires, or when the specified has cancellation requested. + /// The timeout after which the should be faulted with a if it hasn't otherwise completed. + /// The to monitor for a cancellation request. + /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. + public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken) => + WaitAsync(ValidateTimeout(timeout, ExceptionArgument.timeout), cancellationToken); + + private Task WaitAsync(uint millisecondsTimeout, CancellationToken cancellationToken) + { + if (IsCompleted || (!cancellationToken.CanBeCanceled && millisecondsTimeout == Timeout.UnsignedInfinite)) + { + return this; + } + + if (cancellationToken.IsCancellationRequested) + { + return FromCanceled(cancellationToken); + } + + if (millisecondsTimeout == 0) + { + return FromException(new TimeoutException()); + } + + return new CancellationPromise(this, millisecondsTimeout, cancellationToken); + } + + /// Task that's completed when another task, timeout, or cancellation token triggers. + private protected sealed class CancellationPromise : Task, ITaskCompletionAction + { + /// The source task. It's stored so that we can remove the continuation from it upon timeout or cancellation. + private readonly Task _task; + /// Cancellation registration used to unregister from the token source upon timeout or the task completing. + private readonly CancellationTokenRegistration _registration; + /// The timer used to implement the timeout. It's stored so that it's rooted and so that we can dispose it upon cancellation or the task completing. + private readonly TimerQueueTimer? _timer; + + internal CancellationPromise(Task source, uint millisecondsDelay, CancellationToken token) + { + Debug.Assert(source != null); + Debug.Assert(millisecondsDelay != 0); + + // Register with the target task. + _task = source; + source.AddCompletionAction(this); + + // Register with a timer if it's needed. + if (millisecondsDelay != Timeout.UnsignedInfinite) + { + _timer = new TimerQueueTimer(static state => + { + var thisRef = (CancellationPromise)state!; + if (thisRef.TrySetException(new TimeoutException())) + { + thisRef.Cleanup(); + } + }, this, millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); + } + + // Register with the cancellation token. + _registration = token.UnsafeRegister(static (state, cancellationToken) => + { + var thisRef = (CancellationPromise)state!; + if (thisRef.TrySetCanceled(cancellationToken)) + { + thisRef.Cleanup(); + } + }, this); + + // If one of the callbacks fired, it's possible they did so prior to our having registered the other callbacks, + // and thus cleanup may have missed those additional registrations. Just in case, check here, and if we're + // already completed, unregister everything again. Unregistration is idempotent and thread-safe. + if (IsCompleted) + { + Cleanup(); + } + } + + bool ITaskCompletionAction.InvokeMayRunArbitraryCode => true; + + void ITaskCompletionAction.Invoke(Task completingTask) + { + Debug.Assert(completingTask.IsCompleted); + + bool set = completingTask.Status switch + { + TaskStatus.Canceled => TrySetCanceled(completingTask.CancellationToken, completingTask.GetCancellationExceptionDispatchInfo()), + TaskStatus.Faulted => TrySetException(completingTask.GetExceptionDispatchInfos()), + _ => completingTask is Task taskTResult ? TrySetResult(taskTResult.Result) : TrySetResult(), + }; + + if (set) + { + Cleanup(); + } + } + + private void Cleanup() + { + _registration.Dispose(); + _timer?.Close(); + _task.RemoveContinuation(this); + } + } + // Convenience method that wraps any scheduler exception in a TaskSchedulerException // and rethrows it. private bool WrappedTryRunInline() @@ -5372,16 +5487,8 @@ public static Task Run(Func?> function, Cancella /// Canceled state. Otherwise, the Task is completed in RanToCompletion state once the specified time /// delay has expired. /// - public static Task Delay(TimeSpan delay, CancellationToken cancellationToken) - { - long totalMilliseconds = (long)delay.TotalMilliseconds; - if (totalMilliseconds < -1 || totalMilliseconds > Timer.MaxSupportedTimeout) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.delay, ExceptionResource.Task_Delay_InvalidDelay); - } - - return Delay((uint)totalMilliseconds, cancellationToken); - } + public static Task Delay(TimeSpan delay, CancellationToken cancellationToken) => + Delay(ValidateTimeout(delay, ExceptionArgument.delay), cancellationToken); /// /// Creates a Task that will complete after a time delay. @@ -5430,6 +5537,17 @@ private static Task Delay(uint millisecondsDelay, CancellationToken cancellation cancellationToken.CanBeCanceled ? new DelayPromiseWithCancellation(millisecondsDelay, cancellationToken) : new DelayPromise(millisecondsDelay); + internal static uint ValidateTimeout(TimeSpan timeout, ExceptionArgument argument) + { + long totalMilliseconds = (long)timeout.TotalMilliseconds; + if (totalMilliseconds < -1 || totalMilliseconds > Timer.MaxSupportedTimeout) + { + ThrowHelper.ThrowArgumentOutOfRangeException(argument, ExceptionResource.Task_InvalidTimerTimeSpan); + } + + return (uint)totalMilliseconds; + } + /// Task that also stores the completion closure and logic for Task.Delay implementation. private class DelayPromise : Task { diff --git a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs index 8667c198913bc..a5f2bcfb7b155 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -817,8 +817,8 @@ private static string GetResourceString(ExceptionResource resource) return SR.Task_ContinueWith_ESandLR; case ExceptionResource.Task_ContinueWith_NotOnAnything: return SR.Task_ContinueWith_NotOnAnything; - case ExceptionResource.Task_Delay_InvalidDelay: - return SR.Task_Delay_InvalidDelay; + case ExceptionResource.Task_InvalidTimerTimeSpan: + return SR.Task_InvalidTimerTimeSpan; case ExceptionResource.Task_Delay_InvalidMillisecondsDelay: return SR.Task_Delay_InvalidMillisecondsDelay; case ExceptionResource.Task_Dispose_NotCompleted: @@ -1022,7 +1022,7 @@ internal enum ExceptionResource AsyncMethodBuilder_InstanceNotInitialized, Task_ContinueWith_ESandLR, Task_ContinueWith_NotOnAnything, - Task_Delay_InvalidDelay, + Task_InvalidTimerTimeSpan, Task_Delay_InvalidMillisecondsDelay, Task_Dispose_NotCompleted, Task_ThrowIfDisposed, diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 432864773300f..dbedabfa893a9 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -11184,6 +11184,9 @@ public static void WaitAll(System.Threading.Tasks.Task[] tasks, System.Threading public static int WaitAny(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; } public static int WaitAny(System.Threading.Tasks.Task[] tasks, System.Threading.CancellationToken cancellationToken) { throw null; } public static int WaitAny(System.Threading.Tasks.Task[] tasks, System.TimeSpan timeout) { throw null; } + public Task WaitAsync(System.TimeSpan timeout) { throw null; } + public Task WaitAsync(System.Threading.CancellationToken cancellationToken) { throw null; } + public Task WaitAsync(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; } public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(params System.Threading.Tasks.Task[] tasks) { throw null; } public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable> tasks) { throw null; } @@ -11480,6 +11483,9 @@ public Task(System.Func function, System.Threading.Tasks.TaskCreationOp public System.Threading.Tasks.Task ContinueWith(System.Func, TNewResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Func, TNewResult> continuationFunction, System.Threading.Tasks.TaskScheduler scheduler) { throw null; } public new System.Runtime.CompilerServices.TaskAwaiter GetAwaiter() { throw null; } + public new System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout) { throw null; } + public new System.Threading.Tasks.Task WaitAsync(System.Threading.CancellationToken cancellationToken) { throw null; } + public new System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; } } public partial class UnobservedTaskExceptionEventArgs : System.EventArgs { diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/TestService.cs b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/TestService.cs index 5d3d9bc808f70..26aea983efe77 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/TestService.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/TestService.cs @@ -106,7 +106,6 @@ public async Task WriteStreamAsync(PipeMessageByteCode code, int command = 0) { DebugTrace("TestService " + ServiceName + ": WriteStreamAsync writing " + code.ToString()); - const int WriteTimeout = 60000; var toWrite = (code == PipeMessageByteCode.OnCustomCommand) ? new byte[] { (byte)command } : new byte[] { (byte)code }; // Wait for the client connection before writing to the pipe. @@ -116,7 +115,7 @@ public async Task WriteStreamAsync(PipeMessageByteCode code, int command = 0) { await _waitClientConnect; } - await _serverStream.WriteAsync(toWrite, 0, 1).TimeoutAfter(WriteTimeout).ConfigureAwait(false); + await _serverStream.WriteAsync(toWrite, 0, 1).WaitAsync(TimeSpan.FromSeconds(60)).ConfigureAwait(false); DebugTrace("TestService " + ServiceName + ": WriteStreamAsync completed"); } diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/TestServiceProvider.cs b/src/libraries/System.ServiceProcess.ServiceController/tests/TestServiceProvider.cs index 54e6ee33942ab..1128d2b29e833 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/TestServiceProvider.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/TestServiceProvider.cs @@ -86,7 +86,7 @@ public async Task ReadPipeAsync() Task readTask; byte[] received = new byte[] { 0 }; readTask = Client.ReadAsync(received, 0, 1); - await readTask.TimeoutAfter(readTimeout).ConfigureAwait(false); + await readTask.WaitAsync(TimeSpan.FromMilliseconds(readTimeout)).ConfigureAwait(false); return received[0]; } diff --git a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs index 43adb3258b61e..f61c6b40631dd 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs @@ -564,7 +564,7 @@ async Task YieldOnceAsync(object s) try { - await tcs.Task.TimeoutAfter(60_000); + await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60)); } catch (Exception e) { diff --git a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs index 1e0e1327d56e4..94f00ce5338a5 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs @@ -334,6 +334,118 @@ public static void GetResult_FaultedTask_MultipleExceptions_ThrowsFirstException Assert.Same(exception, AssertExtensions.Throws(null, () => task.ConfigureAwait(true).GetAwaiter().GetResult())); } + [Fact] + public static void ConfigureAwait_InvalidTimeout_Throws() + { + foreach (TimeSpan timeout in new[] { TimeSpan.FromMilliseconds(-2), TimeSpan.MaxValue, TimeSpan.MinValue }) + { + AssertExtensions.Throws("timeout", () => new TaskCompletionSource().Task.WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => new TaskCompletionSource().Task.WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => new TaskCompletionSource().Task.WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => new TaskCompletionSource().Task.WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => new TaskCompletionSource().Task.WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => new TaskCompletionSource().Task.WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => Task.CompletedTask.WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => Task.CompletedTask.WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => Task.CompletedTask.WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => Task.FromResult(42).WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => Task.FromResult(42).WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => Task.FromResult(42).WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => Task.FromCanceled(new CancellationToken(true)).WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => Task.FromCanceled(new CancellationToken(true)).WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => Task.FromCanceled(new CancellationToken(true)).WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => Task.FromCanceled(new CancellationToken(true)).WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => Task.FromCanceled(new CancellationToken(true)).WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => Task.FromCanceled(new CancellationToken(true)).WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => Task.FromException(new FormatException()).WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => Task.FromException(new FormatException()).WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => Task.FromException(new FormatException()).WaitAsync(timeout, new CancellationToken(true))); + + AssertExtensions.Throws("timeout", () => Task.FromException(new FormatException()).WaitAsync(timeout)); + AssertExtensions.Throws("timeout", () => Task.FromException(new FormatException()).WaitAsync(timeout, CancellationToken.None)); + AssertExtensions.Throws("timeout", () => Task.FromException(new FormatException()).WaitAsync(timeout, new CancellationToken(true))); + } + } + + [Fact] + public static async Task ConfigureAwait_CanceledAndTimedOut_AlreadyCompleted_UsesTaskResult() + { + await Task.CompletedTask.WaitAsync(TimeSpan.Zero); + await Task.CompletedTask.WaitAsync(new CancellationToken(true)); + await Task.CompletedTask.WaitAsync(TimeSpan.Zero, new CancellationToken(true)); + + Assert.Equal(42, await Task.FromResult(42).WaitAsync(TimeSpan.Zero)); + Assert.Equal(42, await Task.FromResult(42).WaitAsync(new CancellationToken(true))); + Assert.Equal(42, await Task.FromResult(42).WaitAsync(TimeSpan.Zero, new CancellationToken(true))); + + await Assert.ThrowsAsync(() => Task.FromException(new FormatException()).WaitAsync(TimeSpan.Zero)); + await Assert.ThrowsAsync(() => Task.FromException(new FormatException()).WaitAsync(new CancellationToken(true))); + await Assert.ThrowsAsync(() => Task.FromException(new FormatException()).WaitAsync(TimeSpan.Zero, new CancellationToken(true))); + + await Assert.ThrowsAsync(() => Task.FromException(new FormatException()).WaitAsync(TimeSpan.Zero)); + await Assert.ThrowsAsync(() => Task.FromException(new FormatException()).WaitAsync(new CancellationToken(true))); + await Assert.ThrowsAsync(() => Task.FromException(new FormatException()).WaitAsync(TimeSpan.Zero, new CancellationToken(true))); + + await Assert.ThrowsAsync(() => Task.FromCanceled(new CancellationToken(true)).WaitAsync(TimeSpan.Zero)); + await Assert.ThrowsAsync(() => Task.FromCanceled(new CancellationToken(true)).WaitAsync(new CancellationToken(true))); + await Assert.ThrowsAsync(() => Task.FromCanceled(new CancellationToken(true)).WaitAsync(TimeSpan.Zero, new CancellationToken(true))); + + await Assert.ThrowsAsync(() => Task.FromCanceled(new CancellationToken(true)).WaitAsync(TimeSpan.Zero)); + await Assert.ThrowsAsync(() => Task.FromCanceled(new CancellationToken(true)).WaitAsync(new CancellationToken(true))); + await Assert.ThrowsAsync(() => Task.FromCanceled(new CancellationToken(true)).WaitAsync(TimeSpan.Zero, new CancellationToken(true))); + } + + [Fact] + public static async Task ConfigureAwait_TimeoutOrCanceled_Throws() + { + var tcs = new TaskCompletionSource(); + var cts = new CancellationTokenSource(); + + await Assert.ThrowsAsync(() => ((Task)tcs.Task).WaitAsync(TimeSpan.Zero)); + await Assert.ThrowsAsync(() => ((Task)tcs.Task).WaitAsync(TimeSpan.FromMilliseconds(1))); + await Assert.ThrowsAsync(() => ((Task)tcs.Task).WaitAsync(TimeSpan.FromMilliseconds(1), cts.Token)); + + await Assert.ThrowsAsync(() => tcs.Task.WaitAsync(TimeSpan.Zero)); + await Assert.ThrowsAsync(() => tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(1))); + await Assert.ThrowsAsync(() => tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(1), cts.Token)); + + Task assert1 = Assert.ThrowsAsync(() => ((Task)tcs.Task).WaitAsync(cts.Token)); + Task assert2 = Assert.ThrowsAsync(() => ((Task)tcs.Task).WaitAsync(Timeout.InfiniteTimeSpan, cts.Token)); + Task assert3 = Assert.ThrowsAsync(() => tcs.Task.WaitAsync(cts.Token)); + Task assert4 = Assert.ThrowsAsync(() => tcs.Task.WaitAsync(Timeout.InfiniteTimeSpan, cts.Token)); + Assert.False(assert1.IsCompleted); + Assert.False(assert2.IsCompleted); + Assert.False(assert3.IsCompleted); + Assert.False(assert4.IsCompleted); + + cts.Cancel(); + await Task.WhenAll(assert1, assert2, assert3, assert4); + } + + [Fact] + public static async Task ConfigureAwait_NoCancellationOrTimeoutOccurs_Success() + { + CancellationTokenSource cts = new CancellationTokenSource(); + + var tcs = new TaskCompletionSource(); + Task t = tcs.Task.WaitAsync(TimeSpan.FromDays(1), cts.Token); + Assert.False(t.IsCompleted); + tcs.SetResult(); + await t; + + var tcsg = new TaskCompletionSource(); + Task tg = tcsg.Task.WaitAsync(TimeSpan.FromDays(1), cts.Token); + Assert.False(tg.IsCompleted); + tcsg.SetResult(42); + Assert.Equal(42, await tg); + } + [Fact] public static void AwaiterAndAwaitableEquality() { diff --git a/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs b/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs index c783740dff3db..a29648a7a4b50 100644 --- a/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs +++ b/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs @@ -63,7 +63,7 @@ public static async Task TaskDropsExecutionContextUponCompletion() try { - await tcs.Task.TimeoutAfter(60_000); // finalizable object should have been collected and finalized + await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60)); // finalizable object should have been collected and finalized } catch (Exception e) { @@ -107,7 +107,7 @@ await Task.Run(delegate // avoid any issues with the stack keeping the object al GC.WaitForPendingFinalizers(); } - await tcs.Task.TimeoutAfter(60_000); // finalizable object should have been collected and finalized + await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60)); // finalizable object should have been collected and finalized GC.KeepAlive(t); // ensure the TCS is stored in the state machine }