public void CheckAutoFlush(int attempt)
        {
            const int    maxAttempts      = 10;
            const double autoFlushSeconds = 1d;

            // Don't retry if we don't have too.
            if (_success)
            {
                Assert.True(true);
                return;
            }

            // Detect errors on other threads.
            _unhandledException = null;
            ExceptionManager.UnhandledException += (source, args) =>
            {
                if (!args.Exception.StackTrace.Contains(@"InMemoryCache", StringComparison.OrdinalIgnoreCase))
                {
                    return;
                }
                _unhandledException = args.Exception;
            };

            var c = new InMemoryCache <string, DisposableMock>(TimeSpan.FromSeconds(autoFlushSeconds), s =>
            {
                var mock = new DisposableMock
                {
                    Id = s
                };
                return(mock);
            }, true, false);
            const string key = @"TEST";
            var          x1  = c[key];

            Assert.Equal(key, x1.Id);
            Thread.Sleep(TimeSpan.FromSeconds(autoFlushSeconds * 1.5d));

            // x1 hasn't been disposed of because AutoFlush is off.
            Assert.False(x1.IsDisposed);
            var x2 = c[key];

            // x1 will be disposed of now because it will have been cleared when the item was selected
            Assert.True(x1.IsDisposed);
            Assert.False(x2.IsDisposed);
            Assert.NotSame(x1, x2);

            // Now clear the cache and try again.
            c.Flush();
            c.Clear();
            c.Flush();
            var flushCount = 0;

            c.Flushed    += (a, b) => { Interlocked.Increment(ref flushCount); };
            c.AutoDispose = true;
            c.AutoDispose = true;
            c.AutoFlush   = true;
            c.AutoFlush   = true; // The second call should take a different path - we can check in code coverage to ensure this is the case.
            Assert.True(c.AutoFlush);
            flushCount = 0;
            x1         = c[key];
            Assert.Equal(key, x1.Id);
            Assert.False(x1.IsDisposed);
            var       loops    = 0;
            const int maxLoops = 5;

            Assert.Equal(c.AutoDispose, true);
            Assert.Equal(c.AutoFlush, true);

            // Allow multiple iterations in case there is some thread starvation.
            while ((loops++ < maxLoops) && (flushCount <= 0))
            {
                Assert.Equal(c.AutoDispose, true);
                Assert.Equal(c.AutoFlush, true);

                // While we are asleep all expired members of the cache should be automatically disposed of
                Thread.Sleep(TimeSpan.FromSeconds(autoFlushSeconds));

                Assert.Equal(c.AutoDispose, true);
                Assert.Equal(c.AutoFlush, true);
            }

            try
            {
                Assert.Null(_unhandledException);

                // Now x1 has been disposed, even though it hasn't been re-fetched.
                Assert.True(x1.IsDisposed, "Cached value has been disposed of.");

                // There has been a flush, without us needing to do anything.
                Assert.True(flushCount >= 1, "Auto-flush is responsible for disposing of the cached value.");

                _success = true;
            }
            catch
            {
                if (attempt >= maxAttempts)
                {
                    // Allow a couple of attempts because occasionally it fails for no reason.
                    throw;
                }
            }
        }