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); }
public override void Send(SendOrPostCallback d, object state) { worker.Post(() => d(state)).Wait(); }