/// <summary>
        /// Begins an external session export
        /// </summary>
        /// <param name="Key">Session key</param>
        /// <param name="Reader">Method to call to kickstart export</param>
        /// <param name="StateObject">State object</param>
        /// <returns>Result of the operation</returns>
        public SessionActionResult BeginExport(string Key, SessionReadHandler Reader, object StateObject)
        {
            // Look for session using a reader lock.
            // If session is not found, return not found;
            // If session is found:
            // Perform an atomic compare exchange on the variable 'InUse'
            // if session is in Use, try read again from the start.
            // if session is not in use, call delegate and return OK response -- do not reset inuse property

            return(Read(Key, Reader, StateObject, true));
        }
        /// <summary>
        /// Reads a stored session
        /// </summary>
        /// <param name="Key">Session Key</param>
        /// <param name="Reader">Method to call to complete read</param>
        /// <param name="StateObject">State object</param>
        /// <returns>Result of read action</returns>
        public SessionActionResult Read(string Key, SessionReadHandler Reader, object StateObject)
        {
            // Look for session using a reader lock.
            // If session is not found, return false;
            // If session is found:
            // Perform an atomic compare exchange on the variable 'InUse'
            // if session is in Use, try read again from the start.
            // if session is not in use, call delegate and return OK

            return(Read(Key, Reader, StateObject, false));
        }
        /// <summary>
        /// Reads a stored session
        /// </summary>
        /// <param name="Key">Session Key</param>
        /// <param name="Reader">Method to call to complete read</param>
        /// <param name="StateObject">State object</param>
        /// <param name="isExporting">Indicates if the session is to be exported</param>
        /// <returns>Result of read action</returns>
        private SessionActionResult Read(string Key, SessionReadHandler Reader, object StateObject, bool isExporting)
        {
            if (Key == null)
            {
                throw new ArgumentNullException("Key");
            }

            bool tryAgain;
            bool sessionIslocked = false;

            Diags.ResetDeadLockCounter(); //Reset Dead lock counter

            do
            {
                tryAgain = false;
                AcquireReadLock();
                ISessionObject entry;
                try
                {
                    dict.TryGetValue(Key, out entry);
                }
                finally
                {
                    ReleaseReadLock();
                }

                if (entry == null)
                {
                    //Session not found
                    Diags.LogSessionNotFound(Key);
                    return(SessionActionResult.NotFound);
                }
                else
                {
                    //Session Found
                    if (entry.CompareExchangeIsInUse(true, false) == false)
                    {
                        //The InUse flag has been set and now this thread has exclusive access to this session object

                        try
                        {
                            //Set IsExporting flag for this entry if item is to be exported
                            if (isExporting)
                            {
                                entry.IsExporting = true;
                            }

                            //Call Reader Delegate
                            if (Reader != null)
                            {
                                Reader(entry, StateObject);
                            }

                            if (isExporting)
                            {
                                Diags.LogSessionExporting(Key, entry);
                            }
                            else
                            {
                                Diags.LogSessionRead(Key, entry);
                            }
                            sessionIslocked = entry.IsLocked;
                        }
                        finally
                        {
                            if (!isExporting) //Remove inUse property if not exporting
                            {
                                entry.CompareExchangeIsInUse(false, true);
                            }
                        }
                    }
                    else
                    {
                        //Nope, it's still there so check if it's been exported and try again

                        if (entry.IsExporting)
                        {
                            //This session is already been exported so leave
                            Diags.ResetDeadLockCounter();
                            return(SessionActionResult.Exporting);
                        }

                        Thread.Sleep(1); //pause for 1 ms
                        tryAgain = true;
                    }

                    Diags.DetectDeadLock(Key, DeadLockIterationCount); //Signal a deadlock after 2000 iterations
                }
            } while (tryAgain);

            Diags.ResetDeadLockCounter(); //Signal deadlock was freed

            if (sessionIslocked && !isExporting)
            {
                Diags.LogSessionIsLocked(Key);
                return(SessionActionResult.Locked);
            }
            else
            {
                return(SessionActionResult.OK);
            }
        }