Skip to content
30 changes: 2 additions & 28 deletions Stack/Opc.Ua.Core/Stack/Tcp/ChannelAsyncOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ public async Task<T> EndAsync(
try
{
Task<bool> awaitableTask = m_tcs.Task;
#if NET6_0_OR_GREATER
if (timeout != int.MaxValue)
{
awaitableTask = m_tcs.Task
Expand All @@ -259,34 +258,9 @@ public async Task<T> EndAsync(
{
awaitableTask = m_tcs.Task.WaitAsync(ct);
}
#else
if (timeout != int.MaxValue || ct != default)
if (!await awaitableTask.ConfigureAwait(false))
{
using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
Task delay = Task.Delay(timeout, cts.Token);
Task completedTask = await Task.WhenAny(m_tcs.Task, delay)
.ConfigureAwait(false);
cts.Cancel(); // Always cancel the (possibly infinite) timeout
if (m_tcs.Task == completedTask)
{
if (!m_tcs.Task.Result)
{
badRequestInterrupted = true;
}
}
else
{
m_tcs.TrySetCanceled(ct);
badRequestInterrupted = true;
}
}
else
#endif
{
if (!await awaitableTask.ConfigureAwait(false))
{
badRequestInterrupted = true;
}
badRequestInterrupted = true;
}
}
catch (TimeoutException)
Expand Down
47 changes: 46 additions & 1 deletion Stack/Opc.Ua.Types/Polyfills/System.Threading.Tasks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,51 @@ namespace System.Threading.Tasks
/// </summary>
public static class PolyFills
{
#if !NET6_0_OR_GREATER
/// <summary>
/// Gets a System.Threading.Tasks.Task that will complete when this System.Threading.Tasks.Task
/// completes, when the specified timeout expires, or when the specified System.Threading.CancellationToken
/// </summary>
/// <typeparam name="T">Task return type</typeparam>
/// <param name="task">The task to wait for. Can't be <see langword="null"></see></param>
/// <param name="timeout">
/// The timeout after which the System.Threading.Tasks.Task should be faulted with
/// <br></br>a System.TimeoutException if it hasn't otherwise completed.
/// </param>
/// <param name="ct">The System.Threading.CancellationToken to monitor for a cancellation request.</param>
/// <returns>The System.Threading.Tasks.Task representing the asynchronous wait. It may or
/// may not be the same instance as the current instance.</returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="TimeoutException"></exception>
public static async Task<T> WaitAsync<T>(this Task<T> task, TimeSpan timeout, CancellationToken ct = default)
{
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}
using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
cts.CancelAfter(timeout);
try
{
var tcs = new TaskCompletionSource<bool>();
using (cts.Token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false))
{
Task completedTask = await Task.WhenAny(task, tcs.Task).ConfigureAwait(false);
if (task != completedTask)
{
ct.ThrowIfCancellationRequested();
throw new TimeoutException("The operation has timed out.");
}
}
return await task.ConfigureAwait(false);
}
catch (OperationCanceledException) when (!ct.IsCancellationRequested)
{
throw new TimeoutException("The operation has timed out.");
}
}
#endif

#if !NET8_0_OR_GREATER
// Copyright Stephen Cleary Nito.AsyncEx

Expand Down Expand Up @@ -72,7 +117,7 @@ private static async Task DoWaitAsync(
Task task,
CancellationToken cancellationToken)
{
var cancelTaskSource =
using var cancelTaskSource =
new CancellationTokenTaskSource<object>(cancellationToken);
await (await Task.WhenAny(task, cancelTaskSource.Task).ConfigureAwait(false))
.ConfigureAwait(false);
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "1.5.378-preview",
"version": "1.5.378",
"versionHeightOffset": 0,
"nugetPackageVersion": {
"semVer": 2
Expand Down
Loading