public async Task <CFHTTPMessage> Open(WorkerThread worker,
                                               CancellationToken cancellationToken)
        {
            this.worker = worker;
            openTcs     = new TaskCompletionSource <CFHTTPMessage> ();
            openCts     = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

            openCts.Token.Register(() => OnCanceled());

            mainThread = Thread.CurrentThread;

            try {
                if (worker != null)
                {
                    await worker.Post(c => DoOpen(), openCts.Token);
                }
                else
                {
                    DoOpen();
                }
                var result = await openTcs.Task;
                return(result);
            } finally {
                openCts.Dispose();
                openCts = null;
            }
        }
        /*
         * Under normal circumstances, we're running on the main thread,
         * so we could do without all the locking.
         *
         * However, we're exposing a System.IO.Stream to the user, who
         * might be using ConfigureAwait (false).
         *
         * Ideally, consumers of the API should either only access the
         * stream from the main thread or use a 'WorkerThread'.
         *
         */

        void StartOperation(IOperation operation)
        {
            bool isCrossThread;

            lock (syncRoot) {
                if (!open || (currentOperation != null))
                {
                    throw new InvalidOperationException();
                }

                if (canceled)
                {
                    operation.SetCanceled();
                    return;
                }
                if (lastError != null)
                {
                    operation.SetException(lastError);
                    return;
                }
                if (completed)
                {
                    operation.SetCompleted();
                    return;
                }
                currentOperation = operation;

                isCrossThread = CheckCrossThreadAccess();

                if (!bytesAvailable)
                {
                    return;
                }
            }

            /*
             * The server already sent us the OnBytesAvailable() event
             * before the operation started.
             *
             * If we have a worker thread, we simply handle it there and
             * don't have to worry about any locking or anything.
             *
             */
            if ((worker != null) && !Thread.CurrentThread.Equals(workerThread))
            {
                worker.Post(() => {
                    if (bytesAvailable)
                    {
                        OnBytesAvailable(false);
                    }
                }
                            );
                return;
            }

            /*
             * We're on the main / worker thread, so we don't need any locking.
             */
            if (!isCrossThread)
            {
                OnBytesAvailable(false);
                return;
            }

            /*
             * Ok, now it's getting complicated: we're neither on the main nor on
             * the worker thread, so we need to do some locking here.
             *
             */
            Monitor.Enter(syncRoot);
            if (!bytesAvailable)
            {
                Monitor.Exit(syncRoot);
                return;
            }

            OnBytesAvailable(true);
        }
Exemple #3
0
 public override void Send(SendOrPostCallback d, object state)
 {
     worker.Post(() => d(state)).Wait();
 }