Search code examples
c#multithreadingconstrained-execution-reg

How to break out a loop contains only a constrained execution region (CER)


I'm using a constrained execution region (CER) to protect the section of code within a while loop of a thread:

private static void MyThreadFunc()
{
    try {
        ...
        while (true)
        {
            RuntimeHelpers.PrepareConstrainedRegions();
            try { }
            finally
            {
                // do something not to be aborted
            }
            Thread.Sleep(1);    // allow while loop to be broken out
        }
    }
    catch (ThreadAbortException e)
    {
         // handle the exception 
    }
}

The problem is if I do not introduce the Thread.Sleep(1) statement at the end of the while loop, any attempt to call Thread.Abort() on the thread hangs. Is there any better method to abort the thread without using the Thread.Sleep() function?


Solution

  • I don't know why you need to abort the thread manually as CLR will do it once it's completed or use Thread.Join to wait until it terminates. But you can make use of the ManualResetEvent to abort it gracefully.

    I have made few changes in the code by replacing the while(true) with the ManualResetEvent

    class ThreadManager
    {
        private ManualResetEvent shutdown = new ManualResetEvent(false);
        private Thread thread;
    
        public void start ()
        {
            thread = new Thread(MyThreadFunc);
            thread.Name = "MyThreadFunc";
            thread.IsBackground = true; 
            thread.Start();
        }
    
        public void Stop ()
        {
            shutdown.Set();
            if (!thread.Join(2000)) //2 sec to stop 
            { 
                thread.Abort();
            }
        }
    
        void MyThreadFunc ()
        {
            while (!shutdown.WaitOne(0))
            {
                // call with the work you need to do
                try {
                        RuntimeHelpers.PrepareConstrainedRegions();
                        try { }
                        finally
                        {
                            // do something not to be aborted
                        }
                    }
                    catch (ThreadAbortException e)
                    {
                            // handle the exception 
                    }
            }
        }
    }