/// <summary> /// <para>Processes async queued requests that are blocked on needing a free pooled stream /// works as follows: /// 1. while there are blocked requests, take one out of the queue /// 2. Wait for a free connection, when one becomes avail, then notify the request that its there /// 3. repeat 1 until there are no more queued requests /// 4. if there are no more requests waiting to for a free stream, then close down this thread ///</para> /// </summary> private void AsyncThread() { do { while (m_QueuedRequests.Count > 0) { bool continueLoop = true; AsyncConnectionPoolRequest asyncState = null; lock (m_QueuedRequests) { asyncState = (AsyncConnectionPoolRequest)m_QueuedRequests.Dequeue(); } WaitHandle [] localWaitHandles = m_WaitHandles; PooledStream PooledStream = null; try { while ((PooledStream == null) && continueLoop) { int result = WaitHandle.WaitAny(localWaitHandles, asyncState.CreationTimeout, false); PooledStream = Get(asyncState.OwningObject, result, ref continueLoop, ref localWaitHandles); } PooledStream.Activate(asyncState.OwningObject, asyncState.AsyncCallback); } catch (Exception e) { if (PooledStream != null) { PooledStream.Close(); PutConnection(PooledStream, asyncState.OwningObject, asyncState.CreationTimeout); } asyncState.AsyncCallback(asyncState.OwningObject, e); } catch { if (PooledStream != null) { PooledStream.Close(); PutConnection(PooledStream, asyncState.OwningObject, asyncState.CreationTimeout); } asyncState.AsyncCallback(asyncState.OwningObject, new Exception(SR.GetString(SR.net_nonClsCompliantException))); } } Thread.Sleep(500); lock (m_QueuedRequests) { if (m_QueuedRequests.Count == 0) { m_AsyncThread = null; break; } } } while (true); }
/// <devdoc> /// <para>Attempts to create a PooledStream, by trying to get a pooled Connection, /// or by creating its own new one</para> /// </devdoc> internal PooledStream GetConnection(object owningObject, GeneralAsyncDelegate asyncCallback, int creationTimeout) { int result; PooledStream stream = null; bool continueLoop = true; bool async = (asyncCallback != null) ? true : false; GlobalLog.Enter("ConnectionPool#" + ValidationHelper.HashString(this) + "::GetConnection"); if (m_State != State.Running) { throw new InternalException(); } Interlocked.Increment(ref m_WaitCount); WaitHandle[] localWaitHandles = m_WaitHandles; if (async) { result = WaitHandle.WaitAny(localWaitHandles, 0, false); if (result != WaitTimeout) { stream = Get(owningObject, result, ref continueLoop, ref localWaitHandles); } if (stream == null) { GlobalLog.Print("GetConnection:" + ValidationHelper.HashString(this) + " going async"); AsyncConnectionPoolRequest asyncState = new AsyncConnectionPoolRequest(this, owningObject, asyncCallback, creationTimeout); QueueRequest(asyncState); } } else { // loop while we don't have an error/timeout and we haven't gotten a stream yet while ((stream == null) && continueLoop) { result = WaitHandle.WaitAny(localWaitHandles, creationTimeout, false); stream = Get(owningObject, result, ref continueLoop, ref localWaitHandles); } } if (null != stream) { // if there is already a stream, then we're not going async if (!stream.IsInitalizing) { asyncCallback = null; } try{ // If activate returns false, it is going to finish asynchronously // and therefore the stream will be returned in a callback and // we should not return it here (return null) if (stream.Activate(owningObject, asyncCallback) == false) { stream = null; } } catch { stream.Close(); PutConnection(stream, owningObject, creationTimeout); throw; } } else if (!async) { throw new InternalException(); } GlobalLog.Leave("ConnectionPool#" + ValidationHelper.HashString(this) + "::GetConnection", ValidationHelper.HashString(stream)); return(stream); }