public void AbortAfterRunCausesImmediateAbortionOfNextRun()
        {
            ThreadAbortScope scope = new ThreadAbortScope();

            int count = 0;
            Assert.IsNull(scope.Run(delegate { count += 1; }));

            scope.Abort();
            Assert.IsNotNull(scope.Run(delegate { count += 1; }));

            Assert.AreEqual(1, count);
        }
        public void AbortWaitsUntilProtectedScopeEndsBeforeOccurring()
        {
            ThreadAbortScope scope = new ThreadAbortScope();

            ManualResetEvent barrier = new ManualResetEvent(false);
            Tasks.StartThreadTask("Background Abort", delegate
            {
                barrier.WaitOne();
                scope.Abort();
            });

            int count = 0;
            Assert.IsNotNull(scope.Run(delegate
            {
                count += 1;

                using (scope.Protect())
                {
                    count += 1;
                    barrier.Set();
                    Thread.Sleep(5000);
                    count += 1;
                }

                count += 1; // should not run
            }));

            Assert.AreEqual(3, count);

            Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100));
        }
        public void AbortBeforeRunCausesImmediateAbortion()
        {
            ThreadAbortScope scope = new ThreadAbortScope();
            int count = 0;

            scope.Abort();
            Assert.IsNotNull(scope.Run(delegate { count += 1; }));

            Assert.AreEqual(0, count);
        }
        public void AbortFromWithinProtectedScopeDoesNotOccurUntilTheProtectedScopeExits()
        {
            bool ranToCompletion = false;
            ThreadAbortScope scope = new ThreadAbortScope();
            ThreadAbortException ex = scope.Run(() =>
            {
                using (scope.Protect())
                {
                    scope.Abort();
                    ranToCompletion = true;
                }
            });

            Assert.IsNotNull(ex, "Should have aborted.");
            Assert.IsTrue(ranToCompletion, "Should have run the action.");
        }
        public void TryToAsynchronouslyHitARunningActionAtRandomTimes()
        {
            const int Iterations = 50;
            Random random = new Random(0);

            for (int i = 0; i < Iterations; i++)
            {
                ThreadAbortScope scope = new ThreadAbortScope();

                Tasks.StartThreadTask("Background Abort", delegate
                {
                    Thread.Sleep(random.Next(5));
                    scope.Abort();
                });

                Stopwatch timeout = Stopwatch.StartNew();
                while (scope.Run(delegate { Thread.SpinWait(1000); }) == null)
                {
                    if (timeout.ElapsedMilliseconds > 500)
                        Assert.Fail("The scope failed to stop the run during iteration {0}.", i);
                }

                Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100));
            }
        }
        public void AbortFromADifferentSourceUnwindsGracefully()
        {
            ThreadAbortScope outerScope = new ThreadAbortScope();

            Assert.IsNotNull(outerScope.Run(delegate
            {
                ThreadAbortScope innerScope = new ThreadAbortScope();
                innerScope.Run(delegate { outerScope.Abort(); });
            }));
        }
        public void AbortFromADifferentThreadUnwindsGracefully()
        {
            ThreadAbortScope scope = new ThreadAbortScope();

            ManualResetEvent barrier = new ManualResetEvent(false);
            Tasks.StartThreadTask("Background Abort", delegate
            {
                barrier.WaitOne();
                scope.Abort(); 
            });

            int count = 0;
            Assert.IsNotNull(scope.Run(delegate
            {
                count += 1;
                barrier.Set();
                Thread.Sleep(5000);

                count += 1; // should not run
            }));

            Assert.AreEqual(1, count);

            Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100));
        }
        public void AbortDuringRunOnSameThreadUnwindsGracefully()
        {
            ThreadAbortScope scope = new ThreadAbortScope();

            int count = 0;
            Assert.IsNotNull(scope.Run(delegate
            {
                count += 1;
                scope.Abort();
                count += 1;
            }));

            Assert.AreEqual(1, count);
        }