示例#1
0
        public static Task TimeoutAfter(this Task task, int millisecondsTimeout)
        {
            if (task is null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            // Short-circuit #1: infinite timeout or task already completed
            if (task.IsCompleted || (millisecondsTimeout == Timeout.Infinite))
            {
                // Either the task has already completed or timeout will never occur.
                // No proxy necessary.
                return(task);
            }

            // tcs.Task will be returned as a proxy to the caller
            var tcs = new TaskCompletionSource <VoidTypeStruct>();

            // Short-circuit #2: zero timeout
            if (millisecondsTimeout == 0)
            {
                // We've already timed out.
                tcs.SetException(new TimeoutException());
                return(tcs.Task);
            }

            // Set up a timer to complete after the specified timeout period
            var timer = new Timer(
                callback: state => ((TaskCompletionSource <VoidTypeStruct>)state !).TrySetException(new TimeoutException()),
                state: tcs,
                dueTime: millisecondsTimeout,
                period: Timeout.Infinite);

            // Wire up the logic for what happens when source task completes
            _ = task.ContinueWith(
                (antecedent, state) =>
            {
                // Recover our state data
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
                var tuple = (Tuple <Timer, TaskCompletionSource <VoidTypeStruct> >)state;
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.

                // Cancel the Timer
                tuple !.Item1.Dispose();

                // Marshal results to proxy
                MarshalTaskResults(antecedent, tuple.Item2);
            },
                Tuple.Create(timer, tcs),
                CancellationToken.None,
                TaskContinuationOptions.ExecuteSynchronously,
                TaskScheduler.Default);

            return(tcs.Task);
        }
示例#2
0
 /// <inheritdoc />
 public void Dispose()
 {
     Item1.Dispose();
     Item2.Dispose();
 }