Пример #1
0
        public void DefaultCancellationTokenRegistration()
        {
            var registration = new CancellationTokenRegistration ();

            // shouldn't throw
            registration.Dispose ();
        }
        // Similar to TaskFactory.FromAsync, except it supports cancellation using ICancellableAsyncResult.
        public static Task FromAsync(Func<AsyncCallback, object, ICancellableAsyncResult> beginMethod,
            Action<IAsyncResult> endMethod, CancellationToken cancellationToken)
        {
            TaskCompletionSource<object> source = new TaskCompletionSource<object>();

            CancellationTokenRegistration cancellationRegistration = new CancellationTokenRegistration();
            bool cancellationRegistrationDisposed = false;
            object cancellationRegistrationLock = new object();

            ICancellableAsyncResult result = beginMethod.Invoke((ar) =>
            {
                lock (cancellationRegistrationLock)
                {
                    cancellationRegistration.Dispose();
                    cancellationRegistrationDisposed = true;
                }

                try
                {
                    endMethod.Invoke(ar);
                    source.SetResult(null);
                }
                catch (OperationCanceledException)
                {
                    source.SetCanceled();
                }
                catch (Exception exception)
                {
                    source.SetException(exception);
                }
            }, null);

            lock (cancellationRegistrationLock)
            {
                if (!cancellationRegistrationDisposed)
                {
                    cancellationRegistration = cancellationToken.Register(result.Cancel);
                }
            }

            if (result.CompletedSynchronously)
            {
                System.Diagnostics.Debug.Assert(source.Task.IsCompleted);
            }

            return source.Task;
        }
Пример #3
0
        public static Task Delay(int dueTimeMs, CancellationToken cancellationToken)
        {
            if (dueTimeMs < -1) throw new ArgumentOutOfRangeException("dueTimeMs", "Invalid due time");
            if (cancellationToken.IsCancellationRequested) return preCanceledTask;
            if (dueTimeMs == 0) return preCompletedTask;

            var tcs = new TaskCompletionSource<object>();
            var ctr = new CancellationTokenRegistration();
            var timer = new Timer(self =>
            {
                ctr.Dispose();
                ((Timer) self).Dispose();
                tcs.TrySetResult(null);
            });
            if (cancellationToken.CanBeCanceled)
                ctr = cancellationToken.Register(() =>
                {
                    timer.Dispose();
                    tcs.TrySetCanceled();
                });
            timer.Change(dueTimeMs, -1);
            return tcs.Task;
        }
Пример #4
0
        public virtual Task<object> ExecuteScalarAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return TaskHelpers.FromCancellation<object>(cancellationToken);
            }
            else
            {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled)
                {
                    registration = cancellationToken.Register(s => ((DbCommand)s).CancelIgnoreFailure(), this);
                }

                try
                {
                    return Task.FromResult<object>(ExecuteScalar());
                }
                catch (Exception e)
                {
                    return TaskHelpers.FromException<object>(e);
                }
                finally
                {
                    registration.Dispose();
                }
            }
        }
Пример #5
0
        protected virtual Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return TaskHelpers.FromCancellation<DbDataReader>(cancellationToken);
            }
            else
            {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled)
                {
                    registration = cancellationToken.Register(s => ((DbCommand)s).CancelIgnoreFailure(), this);
                }

                try
                {
                    return Task.FromResult<DbDataReader>(ExecuteReader(behavior));
                }
                catch (Exception e)
                {
                    return TaskHelpers.FromException<DbDataReader>(e);
                }
                finally
                {
                    registration.Dispose();
                }
            }
        }
Пример #6
0
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            this.CheckDispose();
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("totalMilliSeconds", millisecondsTimeout, SemaphoreSlim.GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
            }
            cancellationToken.ThrowIfCancellationRequested();
            uint startTime = 0U;

            if (millisecondsTimeout != -1 && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }
            bool        result = false;
            Task <bool> task   = null;
            bool        flag   = false;
            CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(SemaphoreSlim.s_cancellationTokenCanceledEventHandler, this);

            try
            {
                SpinWait spinWait = default(SpinWait);
                while (this.m_currentCount == 0 && !spinWait.NextSpinWillYield)
                {
                    spinWait.SpinOnce();
                }
                try
                {
                }
                finally
                {
                    Monitor.Enter(this.m_lockObj, ref flag);
                    if (flag)
                    {
                        this.m_waitCount++;
                    }
                }
                if (this.m_asyncHead != null)
                {
                    task = this.WaitAsync(millisecondsTimeout, cancellationToken);
                }
                else
                {
                    OperationCanceledException ex = null;
                    if (this.m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }
                        try
                        {
                            result = this.WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException ex2)
                        {
                            ex = ex2;
                        }
                    }
                    if (this.m_currentCount > 0)
                    {
                        result = true;
                        this.m_currentCount--;
                    }
                    else if (ex != null)
                    {
                        throw ex;
                    }
                    if (this.m_waitHandle != null && this.m_currentCount == 0)
                    {
                        this.m_waitHandle.Reset();
                    }
                }
            }
            finally
            {
                if (flag)
                {
                    this.m_waitCount--;
                    Monitor.Exit(this.m_lockObj);
                }
                cancellationTokenRegistration.Dispose();
            }
            if (task == null)
            {
                return(result);
            }
            return(task.GetAwaiter().GetResult());
        }
Пример #7
0
        protected virtual Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) {
            if (cancellationToken.IsCancellationRequested) {
                return ADP.CreatedTaskWithCancellation<DbDataReader>();
            }
            else {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled) {
                    registration = cancellationToken.Register(CancelIgnoreFailure);
                }

                try {
                    return Task.FromResult<DbDataReader>(ExecuteReader(behavior));
                }
                catch (Exception e) {
                    registration.Dispose();
                    return ADP.CreatedTaskWithException<DbDataReader>(e);
                }
            }
        }
		public void ReEntrantRegistrationTest ()
		{
			bool unregister = false;
			bool register = false;
			var source = new CancellationTokenSource ();
			var token = source.Token;

			var reg = new CancellationTokenRegistration ();
			Console.WriteLine ("Test1");
			token.Register (() => reg.Dispose ());
			reg = token.Register (() => unregister = true);
			token.Register (() => { Console.WriteLine ("Gnyah"); token.Register (() => register = true); });
			source.Cancel ();

			Assert.IsFalse (unregister);
			Assert.IsTrue (register);
		}
        public async Task CloseNetworkConnectionAsync(CancellationToken cancellationToken)
        {
            // need to yield here to make sure that we don't get any exception synchronously
            await Task.Yield();

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
            }

            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();

            try
            {
                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
                }
#if DEBUG
                // When using fast path only one outstanding read is permitted. By switching into opaque mode
                // via IWebSocketStream.SwitchToOpaqueMode (see more detailed comments in interface definition)
                // caller takes responsibility for enforcing this constraint.
                Debug.Assert(Interlocked.Increment(ref _outstandingOperations._writes) == 1,
                    "Only one outstanding write allowed at any given time.");
#endif
                _writeTaskCompletionSource = new TaskCompletionSource<object>();
                _writeEventArgs.SetShouldCloseOutput();
                if (WriteAsyncFast(_writeEventArgs))
                {
                    await _writeTaskCompletionSource.Task.SuppressContextFlow();
                }
            }
            catch (Exception error)
            {
                if (!s_CanHandleException(error))
                {
                    throw;
                }

                // throw OperationCancelledException when canceled by the caller
                // otherwise swallow the exception
                cancellationToken.ThrowIfCancellationRequested();
            }
            finally
            {
                cancellationTokenRegistration.Dispose();

                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
            }
        }
        private async Task MultipleWriteAsyncCore(IList<ArraySegment<byte>> sendBuffers, CancellationToken cancellationToken)
        {
            Debug.Assert(sendBuffers != null, "'sendBuffers' MUST NOT be NULL.");
            Debug.Assert(sendBuffers.Count == 2, "'sendBuffers.Count' MUST be '2' at this point.");

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
            }

            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();

            try
            {
                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
                }
#if DEBUG
                // When using fast path only one outstanding read is permitted. By switching into opaque mode
                // via IWebSocketStream.SwitchToOpaqueMode (see more detailed comments in interface definition)
                // caller takes responsibility for enforcing this constraint.
                Debug.Assert(Interlocked.Increment(ref _outstandingOperations._writes) == 1,
                    "Only one outstanding write allowed at any given time.");
#endif
                _writeTaskCompletionSource = new TaskCompletionSource<object>();
                _writeEventArgs.SetBuffer(null, 0, 0);
                _writeEventArgs.BufferList = sendBuffers;
                if (WriteAsyncFast(_writeEventArgs))
                {
                    await _writeTaskCompletionSource.Task.SuppressContextFlow();
                }
            }
            catch (Exception error)
            {
                if (s_CanHandleException(error))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                throw;
            }
            finally
            {
                cancellationTokenRegistration.Dispose();

                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
            }
        }
Пример #11
0
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            CheckDispose();

            // Validate input
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(millisecondsTimeout), millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Perf: Check the stack timeout parameter before checking the volatile count
            if (millisecondsTimeout == 0 && m_currentCount == 0)
            {
                // Pessimistic fail fast, check volatile count outside lock (only when timeout is zero!)
                return(false);
            }

            uint startTime = 0;

            if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }

            bool        waitSuccessful = false;
            Task <bool>?asyncWaitTask  = null;
            bool        lockTaken      = false;

            // Register for cancellation outside of the main lock.
            // NOTE: Register/unregister inside the lock can deadlock as different lock acquisition orders could
            //      occur for (1)this.m_lockObjAndDisposed and (2)cts.internalLock
            CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.UnsafeRegister(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                // Perf: first spin wait for the count to be positive.
                // This additional amount of spinwaiting in addition
                // to Monitor.Enter()'s spinwaiting has shown measurable perf gains in test scenarios.
                if (m_currentCount == 0)
                {
                    // Monitor.Enter followed by Monitor.Wait is much more expensive than waiting on an event as it involves another
                    // spin, contention, etc. The usual number of spin iterations that would otherwise be used here is increased to
                    // lessen that extra expense of doing a proper wait.
                    int spinCount = SpinWait.SpinCountforSpinBeforeWait * 4;

                    SpinWait spinner = default;
                    while (spinner.Count < spinCount)
                    {
                        spinner.SpinOnce(sleep1Threshold: -1);

                        if (m_currentCount != 0)
                        {
                            break;
                        }
                    }
                }
                // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
                // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
                try { }
                finally
                {
                    Monitor.Enter(m_lockObjAndDisposed, ref lockTaken);
                    if (lockTaken)
                    {
                        m_waitCount++;
                    }
                }

                // If there are any async waiters, for fairness we'll get in line behind
                // then by translating our synchronous wait into an asynchronous one that we
                // then block on (once we've released the lock).
                if (m_asyncHead != null)
                {
                    Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't");
                    asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
                }
                // There are no async waiters, so we can proceed with normal synchronous waiting.
                else
                {
                    // If the count > 0 we are good to move on.
                    // If not, then wait if we were given allowed some wait duration

                    OperationCanceledException?oce = null;

                    if (m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }

                        // Prepare for the main wait...
                        // wait until the count become greater than zero or the timeout is expired
                        try
                        {
                            waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException e) { oce = e; }
                    }

                    // Now try to acquire.  We prioritize acquisition over cancellation/timeout so that we don't
                    // lose any counts when there are asynchronous waiters in the mix.  Asynchronous waiters
                    // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
                    // waiter didn't get released because a synchronous waiter was present, we need to ensure
                    // that synchronous waiter succeeds so that they have a chance to release.
                    Debug.Assert(!waitSuccessful || m_currentCount > 0,
                                 "If the wait was successful, there should be count available.");
                    if (m_currentCount > 0)
                    {
                        waitSuccessful = true;
                        m_currentCount--;
                    }
                    else if (oce != null)
                    {
                        throw oce;
                    }

                    // Exposing wait handle which is lazily initialized if needed
                    if (m_waitHandle != null && m_currentCount == 0)
                    {
                        m_waitHandle.Reset();
                    }
                }
            }
            finally
            {
                // Release the lock
                if (lockTaken)
                {
                    m_waitCount--;
                    Monitor.Exit(m_lockObjAndDisposed);
                }

                // Unregister the cancellation callback.
                cancellationTokenRegistration.Dispose();
            }

            // If we had to fall back to asynchronous waiting, block on it
            // here now that we've released the lock, and return its
            // result when available.  Otherwise, this was a synchronous
            // wait, and whether we successfully acquired the semaphore is
            // stored in waitSuccessful.

            return((asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful);
        }
Пример #12
0
        /// <summary>
        /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>,
        /// using a 32-bit signed integer to measure the time interval,
        /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
        /// </summary>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to
        /// wait indefinitely.</param>
        /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
        /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
        /// which represents an infinite time-out.</exception>
        /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            CheckDispose();

            // Validate input
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(
                          "totalMilliSeconds", millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
            }

            cancellationToken.ThrowIfCancellationRequested();

            uint startTime = 0;

            if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }

            bool        waitSuccessful = false;
            Task <bool> asyncWaitTask  = null;
            bool        lockTaken      = false;

            //Register for cancellation outside of the main lock.
            //NOTE: Register/deregister inside the lock can deadlock as different lock acquisition orders could
            //      occur for (1)this.m_lockObj and (2)cts.internalLock
            CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                // Perf: first spin wait for the count to be positive, but only up to the first planned yield.
                //       This additional amount of spinwaiting in addition
                //       to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
                //
                SpinWait spin = new SpinWait();
                while (m_currentCount == 0 && !spin.NextSpinWillYield)
                {
                    spin.SpinOnce();
                }
                // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
                // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
                try { }
                finally
                {
                    m_lock.Acquire();
                    lockTaken = true;
                    if (lockTaken)
                    {
                        m_waitCount++;
                    }
                }

                // If there are any async waiters, for fairness we'll get in line behind
                // then by translating our synchronous wait into an asynchronous one that we
                // then block on (once we've released the lock).
                if (m_asyncHead != null)
                {
                    Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't");
                    asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
                }
                // There are no async waiters, so we can proceed with normal synchronous waiting.
                else
                {
                    // If the count > 0 we are good to move on.
                    // If not, then wait if we were given allowed some wait duration

                    OperationCanceledException oce = null;

                    if (m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }

                        // Prepare for the main wait...
                        // wait until the count become greater than zero or the timeout is expired
                        try
                        {
                            waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException e) { oce = e; }
                    }

                    // Now try to acquire.  We prioritize acquisition over cancellation/timeout so that we don't
                    // lose any counts when there are asynchronous waiters in the mix.  Asynchronous waiters
                    // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
                    // waiter didn't get released because a synchronous waiter was present, we need to ensure
                    // that synchronous waiter succeeds so that they have a chance to release.
                    Debug.Assert(!waitSuccessful || m_currentCount > 0,
                                 "If the wait was successful, there should be count available.");
                    if (m_currentCount > 0)
                    {
                        waitSuccessful = true;
                        m_currentCount--;
                    }
                    else if (oce != null)
                    {
                        throw oce;
                    }

                    // Exposing wait handle which is lazily initialized if needed
                    if (m_waitHandle != null && m_currentCount == 0)
                    {
                        m_waitHandle.Reset();
                    }
                }
            }
            finally
            {
                // Release the lock
                if (lockTaken)
                {
                    m_waitCount--;
                    m_lock.Release();
                }

                // Unregister the cancellation callback.
                cancellationTokenRegistration.Dispose();
            }

            // If we had to fall back to asynchronous waiting, block on it
            // here now that we've released the lock, and return its
            // result when available.  Otherwise, this was a synchronous
            // wait, and whether we successfully acquired the semaphore is
            // stored in waitSuccessful.

            return((asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful);
        }
        private async Task ConnectAsyncCore(Uri uri, CancellationToken cancellationToken)
        {
            HttpWebResponse response = null;
            CancellationTokenRegistration connectCancellation = new CancellationTokenRegistration();
            // Any errors from here on out are fatal and this instance will be disposed.
            try
            {
                HttpWebRequest request = CreateAndConfigureRequest(uri);
                if (Logging.On) Logging.Associate(Logging.WebSockets, this, request);

                connectCancellation = cancellationToken.Register(AbortRequest, request, false);

                response = await request.GetResponseAsync().SuppressContextFlow() as HttpWebResponse;
                Contract.Assert(response != null, "Not an HttpWebResponse");

                if (Logging.On) Logging.Associate(Logging.WebSockets, this, response);

                string subprotocol = ValidateResponse(request, response);

                innerWebSocket = WebSocket.CreateClientWebSocket(response.GetResponseStream(), subprotocol,
                    options.ReceiveBufferSize, options.SendBufferSize, options.KeepAliveInterval, false,
                    options.GetOrCreateBuffer());

                if (Logging.On) Logging.Associate(Logging.WebSockets, this, innerWebSocket);

                // Change internal state to 'connected' to enable the other methods
                if (Interlocked.CompareExchange(ref state, connected, connecting) != connecting)
                {
                    // Aborted/Disposed during connect.
                    throw new ObjectDisposedException(GetType().FullName);
                }
            }
            catch (WebException ex)
            {
                ConnectExceptionCleanup(response);
                WebSocketException wex = new WebSocketException(SR.GetString(SR.net_webstatus_ConnectFailure), ex);
                if (Logging.On) Logging.Exception(Logging.WebSockets, this, "ConnectAsync", wex);
                throw wex;
            }
            catch (Exception ex)
            {
                ConnectExceptionCleanup(response);
                if (Logging.On) Logging.Exception(Logging.WebSockets, this, "ConnectAsync", ex);
                throw;
            }
            finally
            {
                // We successfully connected (or failed trying), disengage from this token.  
                // Otherwise any timeout/cancellation would apply to the full session.
                // In the failure case we need to release the reference to HWR.
                connectCancellation.Dispose();
            }
        }
        public virtual Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                var taskFactory = new TaskFactory<int>();
                return taskFactory.FromCancellation<int>(cancellationToken);
            }
            else
            {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled)
                {
                    registration = cancellationToken.Register(s => ((DbCommand)s).CancelIgnoreFailure(), this);
                }

                try
                {
                    return Task.FromResult<int>(ExecuteNonQuery());
                }
                catch (Exception e)
                {
                    var taskFactory = new TaskFactory<int>();
                    return taskFactory.FromException<int>(e);                    
                }
                finally
                {
                    registration.Dispose();
                }
            }
        }
Пример #15
0
        private async Task<byte[]> EnsureReadAsync(int readSize, CancellationToken token)
        {
            var cancelTaskToken = new CancellationTokenRegistration();
            try
            {
                await _singleReaderSemaphore.WaitAsync(token);

                var buffer = new byte[readSize];
                var length = 0;
                var offset = 0;

                while (length < readSize)
                {
                    readSize = readSize - length;
                    var client = await GetClientAsync();

                    // Read asynchronously to the receive buffer
                    length = await client.GetStream()
                        .ReadAsync(buffer, offset, readSize, token)
                        .WithCancellation(token);
                    if (length <= 0)
                    {
                        // Attempt to trigger a reconnection and throw an error
                        this.TriggerReconnection();
                        throw new ServerDisconnectedException(string.Format("Lost connection to server: {0}", _endpoint));
                    }

                    // Increase the offset in the buffer
                    offset += length;
                }

                return buffer;
            }
            catch
            {
                if (_disposeToken.IsCancellationRequested)
                    throw new ObjectDisposedException("Object is disposing.");
                //TODO add exception test here to see if an exception made us lose a connection Issue #17
                throw;
            }
            finally
            {
                cancelTaskToken.Dispose();
                _singleReaderSemaphore.Release();
            }
        }
        public async override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            if (WebSocketBase.LoggingEnabled)
            {
                Logging.Enter(Logging.WebSockets, this, Methods.WriteAsync,
                    WebSocketHelpers.GetTraceMsgForParameters(offset, count, cancellationToken));
            }
            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();

            try
            {
                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
                }

                WebSocketHelpers.ThrowIfConnectionAborted(m_ConnectStream.Connection, false);
                await base.WriteAsync(buffer, offset, count, cancellationToken).SuppressContextFlow();

                if (WebSocketBase.LoggingEnabled)
                {
                    Logging.Dump(Logging.WebSockets, this, Methods.WriteAsync, buffer, offset, count);
                }
            }
            catch (Exception error)
            {
                if (s_CanHandleException(error))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                throw;
            }
            finally
            {
                cancellationTokenRegistration.Dispose();

                if (WebSocketBase.LoggingEnabled)
                {
                    Logging.Exit(Logging.WebSockets, this,  Methods.WriteAsync, string.Empty);
                }
            }
        }
        public async Task MultipleWriteAsync(IList<ArraySegment<byte>> sendBuffers, CancellationToken cancellationToken)
        {
            Contract.Assert(this.SupportsMultipleWrite, "This method MUST NOT be used for custom NetworkStream implementations.");

            if (WebSocketBase.LoggingEnabled)
            {
                Logging.Enter(Logging.WebSockets, this, Methods.MultipleWriteAsync, string.Empty);
            }
            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();

            try
            {
                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
                }

                WebSocketHelpers.ThrowIfConnectionAborted(m_ConnectStream.Connection, false);
                await ((WebSocketBase.IWebSocketStream)base.BaseStream).MultipleWriteAsync(sendBuffers, cancellationToken).SuppressContextFlow();

                if (WebSocketBase.LoggingEnabled)
                {
                    foreach(ArraySegment<byte> buffer in sendBuffers)
                    {
                        Logging.Dump(Logging.WebSockets, this, Methods.MultipleWriteAsync, buffer.Array, buffer.Offset, buffer.Count);
                    }
                }
            }
            catch (Exception error)
            {
                if (s_CanHandleException(error))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                throw;
            }
            finally
            {
                cancellationTokenRegistration.Dispose();

                if (WebSocketBase.LoggingEnabled)
                {
                    Logging.Exit(Logging.WebSockets, this, Methods.MultipleWriteAsync, string.Empty);
                }
            }
        }
        private async Task WriteAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this, WebSocketValidate.GetTraceMsgForParameters(offset, count, cancellationToken));
            }

            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();

            try
            {
                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
                }

                if (!_inOpaqueMode)
                {
                    await _outputStream.WriteAsync(buffer, offset, count, cancellationToken).SuppressContextFlow();
                }
                else
                {
#if DEBUG
                    // When using fast path only one outstanding read is permitted. By switching into opaque mode
                    // via IWebSocketStream.SwitchToOpaqueMode (see more detailed comments in interface definition)
                    // caller takes responsibility for enforcing this constraint.
                    Debug.Assert(Interlocked.Increment(ref _outstandingOperations._writes) == 1,
                        "Only one outstanding write allowed at any given time.");
#endif
                    _writeTaskCompletionSource = new TaskCompletionSource<object>();
                    _writeEventArgs.BufferList = null;
                    _writeEventArgs.SetBuffer(buffer, offset, count);
                    if (WriteAsyncFast(_writeEventArgs))
                    {
                        await _writeTaskCompletionSource.Task.SuppressContextFlow();
                    }
                }
            }
            catch (Exception error)
            {
                if (s_CanHandleException(error))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                throw;
            }
            finally
            {
                cancellationTokenRegistration.Dispose();

                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
            }
        }
        public async Task CloseNetworkConnectionAsync(CancellationToken cancellationToken)
        {
            // need to yield here to make sure that we don't get any exception synchronously
            await Task.Yield();
            if (WebSocketBase.LoggingEnabled)
            {
                Logging.Enter(Logging.WebSockets, this, Methods.CloseNetworkConnectionAsync, string.Empty);
            }

            CancellationTokenSource reasonableTimeoutCancellationTokenSource = null;
            CancellationTokenSource linkedCancellationTokenSource = null;
            CancellationToken linkedCancellationToken = CancellationToken.None;

            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();
            
            int bytesRead = 0;
            try
            {
                reasonableTimeoutCancellationTokenSource = 
                    new CancellationTokenSource(WebSocketHelpers.ClientTcpCloseTimeout);
                linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
                    reasonableTimeoutCancellationTokenSource.Token,
                    cancellationToken);
                linkedCancellationToken = linkedCancellationTokenSource.Token;
                cancellationTokenRegistration = linkedCancellationToken.Register(s_OnCancel, this, false);

                WebSocketHelpers.ThrowIfConnectionAborted(m_ConnectStream.Connection, true);
                byte[] buffer = new byte[1];
                if (m_WebSocketConnection != null && m_InOpaqueMode)
                {
                    bytesRead = await m_WebSocketConnection.ReadAsyncCore(buffer, 0, 1, linkedCancellationToken, true).SuppressContextFlow<int>();
                }
                else
                {
                    bytesRead = await base.ReadAsync(buffer, 0, 1, linkedCancellationToken).SuppressContextFlow<int>();
                }

                if (bytesRead != 0)
                {
                    Contract.Assert(false, "'bytesRead' MUST be '0' at this point. Instead more payload was received ('" + buffer[0].ToString() + "')");

                    if (WebSocketBase.LoggingEnabled)
                    {
                        Logging.Dump(Logging.WebSockets, this, Methods.CloseNetworkConnectionAsync, buffer, 0, bytesRead);
                    }

                    throw new WebSocketException(WebSocketError.NotAWebSocket);
                }
            }
            catch (Exception error)
            {
                if (!s_CanHandleException(error))
                {
                    throw;
                }

                // throw OperationCancelledException when canceled by the caller
                // ignore cancellation due to the timeout
                cancellationToken.ThrowIfCancellationRequested();
            }
            finally
            {
                cancellationTokenRegistration.Dispose();
                if (linkedCancellationTokenSource != null)
                {
                    linkedCancellationTokenSource.Dispose();
                }

                if (reasonableTimeoutCancellationTokenSource != null)
                {
                    reasonableTimeoutCancellationTokenSource.Dispose();
                }

                if (WebSocketBase.LoggingEnabled)
                {
                    Logging.Exit(Logging.WebSockets, this, Methods.CloseNetworkConnectionAsync, bytesRead);
                }
            }
        }
Пример #20
0
		public Task<XmlReader> ExecuteXmlReaderAsync (CancellationToken cancellationToken)
		{
			TaskCompletionSource<XmlReader> source = new TaskCompletionSource<XmlReader>();

			CancellationTokenRegistration registration = new CancellationTokenRegistration();
			if (cancellationToken.CanBeCanceled) {
				if (cancellationToken.IsCancellationRequested) {
					source.SetCanceled();
					return source.Task;
				}
				registration = cancellationToken.Register(CancelIgnoreFailure);
			}

			Task<XmlReader> returnedTask = source.Task;
			try {
				// TODO: RegisterForConnectionCloseNotification(ref returnedTask);

				Task<XmlReader>.Factory.FromAsync(BeginExecuteXmlReader, EndExecuteXmlReader, null).ContinueWith((t) => {
					registration.Dispose();
					if (t.IsFaulted) {
						Exception e = t.Exception.InnerException;
						source.SetException(e);
					}
					else {
						if (t.IsCanceled) {
							source.SetCanceled();
						}
						else {
							source.SetResult(t.Result);
						}
					}
				}, TaskScheduler.Default);
			}
			catch (Exception e) {
				source.SetException(e);
			}

			return returnedTask;
		}
        private async Task<int> ReadAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            if (WebSocketBase.LoggingEnabled)
            {
                Logging.Enter(Logging.WebSockets, this, Methods.ReadAsyncCore, 
                    WebSocketHelpers.GetTraceMsgForParameters(offset, count, cancellationToken));
            }

            CancellationTokenRegistration cancellationTokenRegistration = new CancellationTokenRegistration();

            int bytesRead = 0;
            try
            {
                if (cancellationToken.CanBeCanceled)
                {
                    cancellationTokenRegistration = cancellationToken.Register(s_OnCancel, this, false);
                }

                if (!m_InOpaqueMode)
                {
                    bytesRead = await m_InputStream.ReadAsync(buffer, offset, count, cancellationToken).SuppressContextFlow<int>();
                }
                else
                {
#if DEBUG
                    // When using fast path only one outstanding read is permitted. By switching into opaque mode
                    // via IWebSocketStream.SwitchToOpaqueMode (see more detailed comments in interface definition)
                    // caller takes responsibility for enforcing this constraint.
                    Contract.Assert(Interlocked.Increment(ref m_OutstandingOperations.m_Reads) == 1,
                        "Only one outstanding read allowed at any given time.");
#endif
                    m_ReadTaskCompletionSource = new TaskCompletionSource<int>();
                    m_ReadEventArgs.SetBuffer(buffer, offset, count);
                    if (!ReadAsyncFast(m_ReadEventArgs))
                    {
                        if (m_ReadEventArgs.Exception != null)
                        {
                            throw m_ReadEventArgs.Exception;
                        }

                        bytesRead = m_ReadEventArgs.BytesTransferred;
                    }
                    else
                    {
                        bytesRead = await m_ReadTaskCompletionSource.Task.SuppressContextFlow<int>();
                    }
                }
            }
            catch (Exception error)
            {
                if (s_CanHandleException(error))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                throw;
            }
            finally
            {
                cancellationTokenRegistration.Dispose();

                if (WebSocketBase.LoggingEnabled)
                {
                    Logging.Exit(Logging.WebSockets, this, Methods.ReadAsyncCore, bytesRead);
                }
            }

            return bytesRead;
        }
Пример #22
0
            private void DeactivateActiveRequest(
                SafeCurlMultiHandle multiHandle, EasyRequest easy, 
                IntPtr gcHandlePtr, CancellationTokenRegistration cancellationRegistration)
            {
                // Remove the operation from the multi handle so we can shut down the multi handle cleanly
                int removeResult = Interop.libcurl.curl_multi_remove_handle(multiHandle, easy._easyHandle);
                Debug.Assert(removeResult == CURLMcode.CURLM_OK, "Failed to remove easy handle"); // ignore cleanup errors in release

                // Release the associated GCHandle so that it's not kept alive forever
                if (gcHandlePtr != IntPtr.Zero)
                {
                    try
                    {
                        GCHandle.FromIntPtr(gcHandlePtr).Free();
                        _activeOperations.Remove(gcHandlePtr);
                    }
                    catch (InvalidOperationException)
                    {
                        Debug.Fail("Couldn't get/free the GCHandle for an active operation while shutting down due to failure");
                    }
                }

                // Undo cancellation registration
                cancellationRegistration.Dispose();
            }
Пример #23
0
        /// <summary>
        /// If AutoSaveChanges is set this method will auto commit changes
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual Task<int> SaveChanges(CancellationToken cancellationToken)
        {
            var source = new TaskCompletionSource<int>();
            if (AutoSaveChanges) {
                var registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled) {
                    if (cancellationToken.IsCancellationRequested) {
                        source.SetCanceled();
                        return source.Task;
                    }
                    registration = cancellationToken.Register(CancelIgnoreFailure);
                }

                try
                {
                    return _uow.SaveChangesAsync(cancellationToken);
                }
                catch (Exception e)
                {
                    source.SetException(e);
                }
                finally
                {
                    registration.Dispose();
                }
            }
            return source.Task;
        }
Пример #24
0
        public virtual Task<object> ExecuteScalarAsync(CancellationToken cancellationToken) {
            if (cancellationToken.IsCancellationRequested) {
                return ADP.CreatedTaskWithCancellation<object>();
            }
            else {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled) {
                    registration = cancellationToken.Register(CancelIgnoreFailure);
                }

                try {
                    return Task.FromResult<object>(ExecuteScalar());
                }
                catch (Exception e) {
                    registration.Dispose();
                    return ADP.CreatedTaskWithException<object>(e);
                }
            }
        }
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            this.CheckDispose();
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("totalMilliSeconds", millisecondsTimeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
            }
            cancellationToken.ThrowIfCancellationRequested();
            long startTimeTicks = 0L;

            if ((millisecondsTimeout != -1) && (millisecondsTimeout > 0))
            {
                startTimeTicks = DateTime.UtcNow.Ticks;
            }
            bool lockTaken = false;
            CancellationTokenRegistration registration = cancellationToken.Register(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                SpinWait wait = new SpinWait();
                while ((this.m_currentCount == 0) && !wait.NextSpinWillYield)
                {
                    wait.SpinOnce();
                }
                try
                {
                }
                finally
                {
                    Monitor.Enter(this.m_lockObj, ref lockTaken);
                    if (lockTaken)
                    {
                        this.m_waitCount++;
                    }
                }
                if (this.m_currentCount == 0)
                {
                    if (millisecondsTimeout == 0)
                    {
                        return(false);
                    }
                    if (!this.WaitUntilCountOrTimeout(millisecondsTimeout, startTimeTicks, cancellationToken))
                    {
                        return(false);
                    }
                }
                this.m_currentCount--;
                if ((this.m_waitHandle != null) && (this.m_currentCount == 0))
                {
                    this.m_waitHandle.Reset();
                }
            }
            finally
            {
                if (lockTaken)
                {
                    this.m_waitCount--;
                    Monitor.Exit(this.m_lockObj);
                }
                registration.Dispose();
            }
            return(true);
        }