コード例 #1
0
            public bool Change(int delay, int period)
            {
                if (delay < -1)
                {
                    throw new ArgumentOutOfRangeException("delay");
                }
                if (period < -1)
                {
                    throw new ArgumentOutOfRangeException("period");
                }

                lock (_lock)
                {
                    if (_cancellationTokenSource != null)
                    {
                        _cancellationTokenSource.Cancel();
                        _cancellationTokenSource.Dispose();
                    }

                    if (delay >= 0)
                    {
                        _cancellationTokenSource = new CancellationTokenSource();
                        Task task = DelayedTask.Delay(TimeSpan.FromMilliseconds(delay), _cancellationTokenSource.Token).Select(BeginInvokeCallback);
                        if (period > 0)
                        {
                            Func <bool> TrueFunction = () => true;
                            Func <Task> delayAndSend = () => DelayedTask.Delay(TimeSpan.FromMilliseconds(period), _cancellationTokenSource.Token).Select(BeginInvokeCallback);
                            task = task.Then(_ => TaskBlocks.While(TrueFunction, delayAndSend));
                        }

                        _task = task;
                    }
                }

                return(true);
            }
コード例 #2
0
        /// <summary>
        /// Returns a response to an Internet request as an asynchronous operation.
        /// </summary>
        /// <remarks>
        /// <para>This operation will not block. The returned <see cref="Task{TResult}"/> object will
        /// complete after a response to an Internet request is available.</para>
        /// </remarks>
        /// <param name="request">The request.</param>
        /// <param name="throwOnError"><see langword="true"/> to throw a <see cref="WebException"/> if the <see cref="HttpWebResponse.StatusCode"/> of the response is greater than 400; otherwise, <see langword="false"/> to return the <see cref="WebResponse"/> in the result for these cases.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/>.</param>
        /// <returns>A <see cref="Task"/> object which represents the asynchronous operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <para>If <paramref name="request"/> is <see langword="null"/>.</para>
        /// </exception>
        /// <exception cref="WebException">
        /// <para>If <see cref="WebRequest.Abort"/> was previously called.</para>
        /// <para>-or-</para>
        /// <para>If the timeout period for the request expired.</para>
        /// <para>-or-</para>
        /// <para>If an error occurred while processing the request.</para>
        /// </exception>
        public static Task <WebResponse> GetResponseAsync(this WebRequest request, bool throwOnError, CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

#if PORTABLE
            bool timeout = false;

            CancellationTokenRegistration cancellationTokenRegistration;
            if (cancellationToken.CanBeCanceled)
            {
                Action cancellationAction = request.Abort;
                cancellationTokenRegistration = cancellationToken.Register(cancellationAction);
            }
            else
            {
                cancellationTokenRegistration = default(CancellationTokenRegistration);
            }

            CancellationTokenSource noRequestTimeoutTokenSource = new CancellationTokenSource();
            WebExceptionStatus      timeoutStatus;
            if (!Enum.TryParse("Timeout", out timeoutStatus))
            {
                timeoutStatus = WebExceptionStatus.UnknownError;
            }

            int requestTimeout;
#if NET45PLUS
            try
            {
                // hack to work around PCL limitation in .NET 4.5
                dynamic dynamicRequest = request;
                requestTimeout = dynamicRequest.Timeout;
            }
            catch (RuntimeBinderException)
            {
                requestTimeout = Timeout.Infinite;
            }
#else
            // hack to work around PCL limitation in .NET 4.0
            var propertyInfo = request.GetType().GetProperty("Timeout", typeof(int));
            if (propertyInfo != null)
            {
                requestTimeout = (int)propertyInfo.GetValue(request, null);
            }
            else
            {
                requestTimeout = Timeout.Infinite;
            }
#endif

            if (requestTimeout >= 0)
            {
                Task timeoutTask = DelayedTask.Delay(TimeSpan.FromMilliseconds(requestTimeout), noRequestTimeoutTokenSource.Token).Select(
                    _ =>
                {
                    timeout = true;
                    request.Abort();
                });
            }

            TaskCompletionSource <WebResponse> completionSource = new TaskCompletionSource <WebResponse>();

            AsyncCallback completedCallback =
                result =>
            {
                try
                {
                    noRequestTimeoutTokenSource.Cancel();
                    noRequestTimeoutTokenSource.Dispose();
                    cancellationTokenRegistration.Dispose();
                    completionSource.TrySetResult(request.EndGetResponse(result));
                }
                catch (WebException ex)
                {
                    if (timeout)
                    {
                        completionSource.TrySetException(new WebException("No response was received during the time-out period for a request.", timeoutStatus));
                    }
                    else if (cancellationToken.IsCancellationRequested)
                    {
                        completionSource.TrySetCanceled();
                    }
                    else if (ex.Response != null && !throwOnError)
                    {
                        completionSource.TrySetResult(ex.Response);
                    }
                    else
                    {
                        completionSource.TrySetException(ex);
                    }
                }
                catch (Exception ex)
                {
                    completionSource.TrySetException(ex);
                }
            };

            IAsyncResult asyncResult = request.BeginGetResponse(completedCallback, null);
            return(completionSource.Task);
#else
            bool timeout = false;
            TaskCompletionSource <WebResponse> completionSource = new TaskCompletionSource <WebResponse>();

            RegisteredWaitHandle timerRegisteredWaitHandle        = null;
            RegisteredWaitHandle cancellationRegisteredWaitHandle = null;
            AsyncCallback        completedCallback =
                result =>
            {
                try
                {
                    if (cancellationRegisteredWaitHandle != null)
                    {
                        cancellationRegisteredWaitHandle.Unregister(null);
                    }

                    if (timerRegisteredWaitHandle != null)
                    {
                        timerRegisteredWaitHandle.Unregister(null);
                    }

                    completionSource.TrySetResult(request.EndGetResponse(result));
                }
                catch (WebException ex)
                {
                    if (timeout)
                    {
                        completionSource.TrySetException(new WebException("No response was received during the time-out period for a request.", WebExceptionStatus.Timeout));
                    }
                    else if (cancellationToken.IsCancellationRequested)
                    {
                        completionSource.TrySetCanceled();
                    }
                    else if (ex.Response != null && !throwOnError)
                    {
                        completionSource.TrySetResult(ex.Response);
                    }
                    else
                    {
                        completionSource.TrySetException(ex);
                    }
                }
                catch (Exception ex)
                {
                    completionSource.TrySetException(ex);
                }
            };

            IAsyncResult asyncResult = request.BeginGetResponse(completedCallback, null);
            if (!asyncResult.IsCompleted)
            {
                if (request.Timeout != Timeout.Infinite)
                {
                    WaitOrTimerCallback timedOutCallback =
                        (object state, bool timedOut) =>
                    {
                        if (timedOut)
                        {
                            timeout = true;
                            request.Abort();
                        }
                    };

                    timerRegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, timedOutCallback, null, request.Timeout, true);
                }

                if (cancellationToken.CanBeCanceled)
                {
                    WaitOrTimerCallback cancelledCallback =
                        (object state, bool timedOut) =>
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            request.Abort();
                        }
                    };

                    cancellationRegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(cancellationToken.WaitHandle, cancelledCallback, null, Timeout.Infinite, true);
                }
            }

            return(completionSource.Task);
#endif
        }