コード例 #1
0
        public void Dispose_Wait_Running_Or_Queued_Tasks()
        {
            // arrange
            TestResource testResource = new TestResource();
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                           );

            // act
            const int taskCount = 1000;

            Task[] tasks = new Task[taskCount];

            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = sharedResource.UseAsync(p => p.Resource.IncreaseCounterNoThreadSafe());
            }

            sharedResource.Dispose();
            testResource.WaitUntilDisposedFor5Minutes();

            // assert
            Assert.IsTrue(testResource.IsDisposed);
            Assert.IsTrue(testResource.Counter == taskCount);
        }
コード例 #2
0
        public void Canceled_Action_Is_Skipped()
        {
            // arrange
            const string            testResource   = "Test";
            SharedResource <string> sharedResource = new SharedResource <string>
                                                     (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                     );
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            cancellationTokenSource.Cancel();

            // act
            bool isCanceledTaskRun = false;
            Task canceledTask      = sharedResource.UseAsync(info =>
            {
                SpinRandomly();
                isCanceledTaskRun = true;
            }, cancellationTokenSource.Token);

            string readTestResource = null;
            Task   normalTask       = sharedResource.UseAsync(info =>
            {
                SpinRandomly();
                readTestResource = testResource;
            });

            Exception cachedException = null;

            try { canceledTask.Wait(); }
            catch (Exception e) { cachedException = e; }

            normalTask.Wait();

            // assert
            Assert.IsFalse(isCanceledTaskRun);
            Assert.IsTrue(cachedException is AggregateException);
            Assert.IsTrue(((AggregateException)cachedException).InnerExceptions.Count == 1);
            Assert.IsTrue(((AggregateException)cachedException).InnerExceptions.First() is OperationCanceledException);
            Assert.IsTrue(readTestResource == testResource);
        }
コード例 #3
0
        public void Dispose_Ignores_Running_Or_Queued_Tasks_That_Canceled_Or_Faulted()
        {
            // arrange
            TestResource testResource = new TestResource();
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                           );

            // act
            const int taskCount = 1000;

            Task[] tasks           = new Task[taskCount];
            int    normalTaskCount = 0;

            for (int i = 0; i < tasks.Length; i++)
            {
                int switchFactor = i % 3;
                if (switchFactor != 0 && switchFactor != 1)
                {
                    normalTaskCount++;
                }

                CancellationTokenSource tokenSource = new CancellationTokenSource();
                tasks[i] = sharedResource.UseAsync(p =>
                {
                    switch (switchFactor)
                    {
                    case 0:
                        throw new InvalidOperationException("Test Exception");

                    case 1:
                        tokenSource.Cancel();
                        tokenSource.Token.ThrowIfCancellationRequested();
                        break;

                    default:
                        p.Resource.IncreaseCounterNoThreadSafe();
                        break;
                    }
                },
                                                   tokenSource.Token);
            }

            sharedResource.Dispose();
            testResource.WaitUntilDisposedFor5Minutes();

            // assert
            Assert.IsTrue(testResource.IsDisposed);
            Assert.IsTrue(testResource.Counter == normalTaskCount);
        }
コード例 #4
0
        public void Next_Action_Runs_If_Previous_Action_Throws_Exception()
        {
            // arrange
            const string            testResource     = "Test";
            const string            exceptionMessage = "Test Exception";
            SharedResource <string> sharedResource   = new SharedResource <string>
                                                       (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                       );

            // act
            Task thrownTask = sharedResource.UseAsync(info =>
            {
                SpinRandomly();
                throw new InvalidOperationException(exceptionMessage);
            });

            string readTestResource = null;
            Task   normalTask       = sharedResource.UseAsync(info =>
            {
                SpinRandomly();
                readTestResource = testResource;
            });

            Exception cachedException = null;

            try { thrownTask.Wait(); }
            catch (Exception e) { cachedException = e; }

            normalTask.Wait();

            // assert
            Assert.IsNotNull(cachedException);
            Assert.IsTrue(cachedException is AggregateException);
            Assert.IsTrue(((AggregateException)cachedException).InnerExceptions.Count == 1);
            Assert.IsTrue(((AggregateException)cachedException).InnerExceptions.First().Message == exceptionMessage);
            Assert.IsTrue(readTestResource == testResource);
        }
コード例 #5
0
        public void One_MaxConcurrentUserCount_Allows_One_Func_Concurrently()
        {
            // arrange
            TestResource testResource = new TestResource();
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                           );

            const int actionCount = 100;

            Task <int>[] tasks         = new Task <int> [actionCount];
            int[]        startCounters = new int[actionCount];
            int[]        endCounters   = new int[actionCount];

            // act
            for (int i = 0; i < actionCount; i++)
            {
                int index = i;
                tasks[index] = sharedResource.UseAsync(info =>
                {
                    startCounters[index] = info.Resource.IncreaseCounter();
                    SpinRandomly();
                    endCounters[index] = info.Resource.DecreaseCounter();
                    return(index);
                });
            }

            Task.WaitAll(tasks);

            // assert
            Assert.IsTrue(testResource.Counter == 0);
            Assert.IsTrue(startCounters.All(p => p == 1));
            Assert.IsTrue(endCounters.All(p => p == 0));

            for (int i = 0; i < actionCount; i++)
            {
                Assert.IsTrue(tasks[i].Result == i);
            }
        }
コード例 #6
0
        public void Disposed_Resource_Throws_Exception_When_Try_To_Use()
        {
            // arrange
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: new TestResource(),
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                           );

            // act
            sharedResource.Dispose();
            Exception cachedException = null;

            try { sharedResource.UseAsync(i => i.Resource.IncreaseCounter()); }
            catch (Exception e) { cachedException = e; }

            // assert
            Assert.IsNotNull(cachedException);
            Assert.IsTrue(cachedException.Message == "This shared resource is already disposed.");
        }
コード例 #7
0
        public void Dispose_Disposes_Resource()
        {
            // arrange
            TestResource testResource = new TestResource();
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: true
                                                           );

            // act
            Task task = sharedResource.UseAsync(p => p.Resource.IncreaseCounterNoThreadSafe());

            sharedResource.Dispose();
            testResource.WaitUntilDisposedFor5Minutes();

            // assert
            Assert.IsTrue(testResource.IsDisposed);
            Assert.IsTrue(testResource.Counter == 1);
        }
コード例 #8
0
        public void Three_MaxConcurrentUserCount_Allows_Three_Actions_Concurrently()
        {
            // arrange
            TestResource testResource = new TestResource();
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: testResource,
                maxConcurrentUserCount: 3,
                isMaxConcurrentUserCountReadOnly: true
                                                           );

            const int actionCount = 100;

            Task[] tasks         = new Task[actionCount];
            int[]  startCounters = new int[actionCount];
            int[]  endCounters   = new int[actionCount];

            // act
            for (int i = 0; i < actionCount; i++)
            {
                int index = i;
                tasks[index] = sharedResource.UseAsync(info =>
                {
                    startCounters[index] = info.Resource.IncreaseCounter();
                    SpinRandomly();
                    endCounters[index] = info.Resource.DecreaseCounter();
                });
            }

            Task.WaitAll(tasks);

            // assert
            Assert.IsTrue(testResource.Counter == 0);
            Assert.IsTrue(startCounters.All(p => p >= 1 && p <= 3));
            Assert.IsTrue(endCounters.All(p => p >= 0 && p <= 2));
        }
コード例 #9
0
        public void One_To_Seven_MaxConcurrentUserCount_Allows_One_To_Seven_Actions_Concurrently()
        {
            // arrange
            TestResource testResource = new TestResource();
            SharedResource <TestResource> sharedResource = new SharedResource <TestResource>
                                                           (
                resource: testResource,
                maxConcurrentUserCount: 1,
                isMaxConcurrentUserCountReadOnly: false
                                                           );

            const int maxMaxConcurrentUserCount = 7;
            const int repeatCount  = 2;
            const int segmentCount = 1000;
            const int actionCount  = maxMaxConcurrentUserCount * repeatCount * segmentCount;

            Task[] tasks         = new Task[actionCount];
            int[]  userIndexes   = new int[actionCount];
            int[]  startCounters = new int[actionCount];
            int[]  endCounters   = new int[actionCount];
            int[]  userCounts    = new int[actionCount];

            // act
            int actionIndex = 0;

            for (int repeatIndex = 0; repeatIndex < repeatCount; repeatIndex++)
            {
                for (int concurrentUserCountIndex = 0; concurrentUserCountIndex < maxMaxConcurrentUserCount; concurrentUserCountIndex++)
                {
                    sharedResource.MaxConcurrentUserCount = repeatIndex % 2 == 0
                                                          ? concurrentUserCountIndex + 1
                                                          : maxMaxConcurrentUserCount - concurrentUserCountIndex;

                    for (int i = 0; i < segmentCount; i++)
                    {
                        int index = actionIndex++;
                        tasks[index] = sharedResource.UseAsync(info =>
                        {
                            userIndexes[index]   = info.UserIndex;
                            startCounters[index] = info.Resource.IncreaseCounter();
                            SpinRandomly();
                            endCounters[index] = info.Resource.DecreaseCounter();
                        },
                                                               TaskCreationOptions.LongRunning);
                        userCounts[index] = sharedResource.UserCount;
                    }

                    Task[] segmentTasks = tasks.Skip(actionIndex - segmentCount).Take(segmentCount).ToArray();
                    Task.WaitAll(segmentTasks);
                }
            }

            // assert
            actionIndex = 0;
            Assert.IsTrue(testResource.Counter == 0);
            Assert.IsTrue(userIndexes.All(p => p >= 0 && p < maxMaxConcurrentUserCount));
            for (int repeatIndex = 0; repeatIndex < repeatCount; repeatIndex++)
            {
                for (int concurrentUserCountIndex = 0; concurrentUserCountIndex < maxMaxConcurrentUserCount; concurrentUserCountIndex++)
                {
                    int maxConcurrentUserCount = repeatIndex % 2 == 0
                                               ? concurrentUserCountIndex + 1
                                               : maxMaxConcurrentUserCount - concurrentUserCountIndex;
                    actionIndex += segmentCount;

                    int[] segmentStartCounters = startCounters.Skip(actionIndex - segmentCount).Take(segmentCount).ToArray();
                    int[] segmentEndCounters   = endCounters.Skip(actionIndex - segmentCount).Take(segmentCount).ToArray();
                    int[] segmentUserCounts    = userCounts.Skip(actionIndex - segmentCount).Take(segmentCount).ToArray();
                    Assert.IsTrue(segmentStartCounters.All(p => p >= 1 && p <= maxConcurrentUserCount));
                    Assert.IsTrue(segmentEndCounters.All(p => p >= 0 && p <= maxConcurrentUserCount - 1));
                    Assert.IsTrue(segmentUserCounts.All(p => p >= 0 && p <= maxMaxConcurrentUserCount));
                }
            }
        }