private bool EnqueueAfterDequeue(ThreadLocalAssemblyContext threadLocalAssemblyContext, AssemblyContext assemblyContext)
        {
            if (threadLocalAssemblyContext.Value != assemblyContext)
            {
                throw new InvalidOperationException(
                          "The specified AssemblyContext has been dequeued on a different thread. "
                          + "An AssemblyContext must be enqueued on the same thread it was dequeued from.");
            }

            threadLocalAssemblyContext.DecrementCount();

            if (threadLocalAssemblyContext.Count == 0)
            {
                try
                {
                    _assemblyContextPool.Enqueue(assemblyContext);
                }
                catch
                {
                    threadLocalAssemblyContext.IncrementCount();
                    throw;
                }
            }

            return(threadLocalAssemblyContext.Count == 0);
        }
        public AssemblyContext Dequeue()
        {
            var data = CallContext.GetData(_instanceID);

            if (data is HashSet <AssemblyContext> )
            {
                throw new InvalidOperationException(
                          "Dequeue() cannot be invoked from the same thread as DequeueAll() until all dequeued AssemblyContext have been returned to the pool.");
            }

            var threadLocalAssemblyContext = data as ThreadLocalAssemblyContext;

            if (threadLocalAssemblyContext == null)
            {
                var assemblyContext = _assemblyContextPool.Dequeue();
                threadLocalAssemblyContext = new ThreadLocalAssemblyContext(assemblyContext);
                CallContext.SetData(_instanceID, threadLocalAssemblyContext);
            }

            threadLocalAssemblyContext.IncrementCount();
            return(threadLocalAssemblyContext.Value);
        }