Beispiel #1
0
        public async Task TestCancelOnOneThreadCancelsOtherTaskIfCanceled()
        {
            AsyncCache <int, int>   cache = new AsyncCache <int, int>();
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            SemaphoreSlim           resetEventSlim          = new SemaphoreSlim(0, 1);

            bool generatorFunc2Called         = false;
            Func <Task <int> > generatorFunc1 = () => Task.Run(async() =>
            {
                await resetEventSlim.WaitAsync(cancellationTokenSource.Token);
                return(1);
            }, cancellationTokenSource.Token);

            Func <Task <int> > generatorFunc2 = () => Task.Run(() =>
            {
                generatorFunc2Called = true;
                return(2);
            });

            // set up two threads that are concurrently updating the async cache for the same key.
            // the only difference is that one thread passes in a cancellation token
            // and the other does not.
            Task <int> getTask1 = cache.GetAsync(key: 1, obsoleteValue: -1, singleValueInitFunc: generatorFunc1, cancellationToken: cancellationTokenSource.Token);

            Task <int> getTask2 = cache.GetAsync(key: 1, obsoleteValue: -1, singleValueInitFunc: generatorFunc2, cancellationToken: cancellationTokenSource.Token);

            // assert that the tasks haven't completed.
            Assert.IsFalse(getTask2.IsCompleted);
            Assert.IsFalse(getTask1.IsCompleted);

            // cancel the first task's cancellation token.
            cancellationTokenSource.Cancel();

            // neither task is complete at this point.
            Assert.IsFalse(getTask2.IsCompleted);
            Assert.IsFalse(getTask1.IsCompleted);

            try
            {
                await getTask1;
                Assert.Fail("Should fail because of cancellation.");
            }
            catch (Exception e)
            {
                Assert.IsTrue(e as OperationCanceledException != null, e.Message);
            }

            try
            {
                await getTask2;
                Assert.Fail("Should fail because of cancellation.");
            }
            catch (Exception e)
            {
                Assert.IsTrue(e as OperationCanceledException != null, e.Message);
            }

            Assert.IsFalse(generatorFunc2Called);
        }
Beispiel #2
0
        public async Task TestGetAsync()
        {
            int numberOfCacheRefreshes = 0;
            Func <int, CancellationToken, Task <int> > refreshFunc = (key, cancellationToken) =>
            {
                Interlocked.Increment(ref numberOfCacheRefreshes);
                return(Task.FromResult(key * 2));
            };

            AsyncCache <int, int> cache = new AsyncCache <int, int>();

            List <Task> tasks = new List <Task>();

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    int key = j;
                    tasks.Add(cache.GetAsync(key, -1, () => refreshFunc(key, CancellationToken.None), CancellationToken.None));
                }
            }

            await Task.WhenAll(tasks);

            Assert.AreEqual(10, numberOfCacheRefreshes);

            Assert.AreEqual(4, await cache.GetAsync(2, -1, () => refreshFunc(2, CancellationToken.None), CancellationToken.None));

            Func <int, CancellationToken, Task <int> > refreshFunc1 = (key, cancellationToken) =>
            {
                Interlocked.Increment(ref numberOfCacheRefreshes);
                return(Task.FromResult(key * 2 + 1));
            };

            List <Task> tasks1 = new List <Task>();

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    int key = j;
                    tasks1.Add(cache.GetAsync(key, key * 2, () => refreshFunc1(key, CancellationToken.None), CancellationToken.None));
                }

                for (int j = 0; j < 10; j++)
                {
                    int key = j;
                    tasks1.Add(cache.GetAsync(key, key * 2, () => refreshFunc1(key, CancellationToken.None), CancellationToken.None));
                }
            }

            await Task.WhenAll(tasks1);

            Assert.AreEqual(20, numberOfCacheRefreshes);
            Assert.AreEqual(5, await cache.GetAsync(2, -1, () => refreshFunc(2, CancellationToken.None), CancellationToken.None));
        }
Beispiel #3
0
        public async Task TestFailureOnOneThreadDoesNotFailAnother()
        {
            AsyncCache <int, int> cache          = new AsyncCache <int, int>();
            SemaphoreSlim         resetEventSlim = new SemaphoreSlim(0, 1);

            Func <Task <int> > generatorFunc1 = () => Task <int> .Run(async() =>
            {
                await resetEventSlim.WaitAsync();
                return(this.GenerateIntFuncThatThrows());
            });

            Func <Task <int> > generatorFunc2 = () => Task.Run(() =>
            {
                return(2);
            });

            // set up two threads that are concurrently updating the async cache for the same key.
            // the only difference is that one thread passes in a cancellation token
            // and the other does not.
            Task <int> getTask1 = cache.GetAsync(key: 1, obsoleteValue: -1, singleValueInitFunc: generatorFunc1, cancellationToken: CancellationToken.None);

            Task <int> getTask2 = cache.GetAsync(key: 1, obsoleteValue: -1, singleValueInitFunc: generatorFunc2, cancellationToken: CancellationToken.None);

            // assert that the tasks haven't completed.
            Assert.IsFalse(getTask2.IsCompleted);
            Assert.IsFalse(getTask1.IsCompleted);

            // release a thread that causes the first to throw.
            resetEventSlim.Release();

            // neither task is complete at this point.
            Assert.IsFalse(getTask2.IsCompleted);
            Assert.IsFalse(getTask1.IsCompleted);

            try
            {
                await getTask1;
                Assert.Fail("Should fail because of exception.");
            }
            catch (Exception e)
            {
                Assert.AreEqual(typeof(InvalidOperationException), e.GetType(), e.Message);
            }

            // task 2 should not fail because task 1 got cancelled.
            int getTaskResult2 = await getTask2;

            Assert.AreEqual(2, getTaskResult2);
        }
Beispiel #4
0
        public async Task TestCancelOnOneThreadDoesNotCancelAnother()
        {
            AsyncCache <int, int>   cache = new AsyncCache <int, int>();
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            SemaphoreSlim           resetEventSlim          = new SemaphoreSlim(0, 1);

            Func <Task <int> > generatorFunc1 = () => Task.Run(async() =>
            {
                await resetEventSlim.WaitAsync(cancellationTokenSource.Token);
                return(1);
            }, cancellationTokenSource.Token);

            Func <Task <int> > generatorFunc2 = () => Task.Run(() =>
            {
                return(2);
            });

            // set up two threads that are concurrently updating the async cache for the same key.
            // the only difference is that one thread passes in a cancellation token
            // and the other does not.
            Task <int> getTask1 = cache.GetAsync(key: 1, obsoleteValue: -1, singleValueInitFunc: generatorFunc1, cancellationToken: cancellationTokenSource.Token);

            Task <int> getTask2 = cache.GetAsync(key: 1, obsoleteValue: -1, singleValueInitFunc: generatorFunc2, cancellationToken: CancellationToken.None);

            // assert that the tasks haven't completed.
            Assert.IsFalse(getTask2.IsCompleted);
            Assert.IsFalse(getTask1.IsCompleted);

            // cancel the first task's cancellation token.
            cancellationTokenSource.Cancel();

            // neither task is complete at this point.
            Assert.IsFalse(getTask2.IsCompleted);
            Assert.IsFalse(getTask1.IsCompleted);

            try
            {
                await getTask1;
                Assert.Fail("Should fail because of cancellation.");
            }
            catch (TaskCanceledException)
            {
            }

            // task 2 should not fail because task 1 got cancelled.
            int getTaskResult2 = await getTask2;

            Assert.AreEqual(2, getTaskResult2);
        }
Beispiel #5
0
        public async Task <IReadOnlyCollection <QueryTag> > GetQueryTagsAsync(CancellationToken cancellationToken = default)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(QueryTagService));
            }

            return(_enableExtendedQueryTags ? await _queryTagCache.GetAsync(cancellationToken : cancellationToken) : CoreQueryTags);
        }
Beispiel #6
0
        /// <inheritdoc />
        public async ValueTask <DicomDataset> GetDicomDatasetAsync(CancellationToken cancellationToken)
        {
            try
            {
                DicomFile file = await _dicomFileCache.GetAsync(cancellationToken : cancellationToken);

                return(file.Dataset);
            }
            catch (DicomFileException)
            {
                throw new InvalidInstanceException(DicomCoreResource.InvalidDicomInstance);
            }
        }
Beispiel #7
0
        public async Task TestConcurrentGetAsync()
        {
            const string key   = "a";
            const string value = "b";

            AsyncCache <string, string> cache = new AsyncCache <string, string>();

            int hitCount = 0;
            await Enumerable.Range(0, 10).ForEachAsync(
                10,
                _ => cache.GetAsync(
                    key,
                    null,
                    () =>
            {
                // No Interlocked, would force barriers
                hitCount++;
                return(Task.FromResult(value));
            },
                    CancellationToken.None));

            Assert.AreEqual(1, hitCount);
        }
Beispiel #8
0
 public Task <T> GetAsync(CancellationToken cancellationToken = default)
 => _cache.GetAsync(forceRefresh: false, cancellationToken: cancellationToken);     // prevent users from forcing refresh