Пример #1
0
        /// <summary>
        /// Execute an action on the thread pool after a specified number of milliseconds.
        /// </summary>
        /// <param name="action">The action to be executed.</param>
        /// <param name="delay">The amount of time to wait before execution, in milliseconds.</param>
        /// <returns>A cancellation token that can be used to cancel the operation.</returns>
        public static ICancellationToken DelayAndExecute(this Action action, int delay)
        {
            object                 waitHandleLock    = new object();
            ManualResetEvent       waitObj           = new ManualResetEvent(false);
            DelayCancellationToken cancellationToken = new DelayCancellationToken(waitObj);
            RegisteredWaitHandle   waitHandle        = null;

            WaitOrTimerCallback callback = (state, timeout) =>
            {
                if (Interlocked.Exchange(ref waitHandleLock, null) == null)
                {
                    waitHandle.Unregister(null);
                    cancellationToken.Dispose();
                }

                if (!timeout)
                {
                    return;
                }

                action();
            };

            waitHandle = ThreadPool.RegisterWaitForSingleObject(waitObj, callback, null, delay, true);

            if (Interlocked.Exchange(ref waitHandleLock, null) == null)
            {
                waitHandle.Unregister(null);
                cancellationToken.Dispose();
            }

            return(cancellationToken);
        }
Пример #2
0
        /// <summary>
        /// Execute an action on the thread pool after a specified number of milliseconds.
        /// </summary>
        /// <param name="action">The action to be executed.</param>
        /// <param name="delay">The amount of time to wait before execution, in milliseconds.</param>
        /// <returns>A cancellation token that can be used to cancel the operation.</returns>
        public static ICancellationToken DelayAndExecute(this Action action, int delay)
        {
            object                 waitHandleLock    = new object();
            ManualResetEvent       waitObj           = new ManualResetEvent(false);
            DelayCancellationToken cancellationToken = new DelayCancellationToken(waitObj);
            RegisteredWaitHandle   waitHandle        = null;

            void callback(object state, bool timeout)
            {
                // Even if the callback timed out, another thread may cancel
                // the cancellation token before we are able to dispose of it
                // so we explicitly cancel the token in order to be sure
#if !MONO
                timeout = timeout && cancellationToken.Cancel();
#else
                timeout = !waitObj.WaitOne(0) && cancellationToken.Cancel();
#endif

                // Both the callback thread and the caller thread will
                // attempt to set the wait handle lock to null, and the
                // last one to do so has to unregister and dispose
                if (Interlocked.Exchange(ref waitHandleLock, null) == null)
                {
                    waitHandle.Unregister(null);
                    cancellationToken.Dispose();
                }

                // If we didn't time out, then the action
                // was canceled by another thread
                if (!timeout)
                {
                    return;
                }

                action();
            }

            waitHandle = ThreadPool.RegisterWaitForSingleObject(waitObj, callback, null, delay, true);

            // Both the callback thread and the caller thread will
            // attempt to set the wait handle lock to null, and the
            // last one to do so has to unregister and dispose
            if (Interlocked.Exchange(ref waitHandleLock, null) == null)
            {
                waitHandle.Unregister(null);
                cancellationToken.Dispose();
            }

            return(cancellationToken);
        }
        /// <summary>
        /// Execute an action on the thread pool after a specified number of milliseconds.
        /// </summary>
        /// <param name="action">The action to be executed.</param>
        /// <param name="delay">The amount of time to wait before execution, in milliseconds.</param>
        /// <returns>A cancellation token that can be used to cancel the operation.</returns>
        public static ICancellationToken DelayAndExecute(this Action action, int delay)
        {
            object waitHandleLock = new object();
            ManualResetEvent waitObj = new ManualResetEvent(false);
            DelayCancellationToken cancellationToken = new DelayCancellationToken(waitObj);
            RegisteredWaitHandle waitHandle = null;

            WaitOrTimerCallback callback = (state, timeout) =>
            {
                // Even if the callback timed out, another thread may cancel
                // the cancellation token before we are able to dispose of it
                // so we explicitly cancel the token in order to be sure
                timeout = timeout && cancellationToken.Cancel();

                // Both the callback thread and the caller thread will
                // attempt to set the wait handle lock to null, and the
                // last one to to do so has to unregister and dispose
                if (Interlocked.Exchange(ref waitHandleLock, null) == null)
                {
                    waitHandle.Unregister(null);
                    cancellationToken.Dispose();
                }

                // If we didn't time out, then the action
                // was cancelled by another thread
                if (!timeout)
                    return;
                
                action();
            };

            waitHandle = ThreadPool.RegisterWaitForSingleObject(waitObj, callback, null, delay, true);

            // Both the callback thread and the caller thread will
            // attempt to set the wait handle lock to null, and the
            // last one to to do so has to unregister and dispose
            if (Interlocked.Exchange(ref waitHandleLock, null) == null)
            {
                waitHandle.Unregister(null);
                cancellationToken.Dispose();
            }

            return cancellationToken;
        }