Search code examples
c#multithreadingoperating-systempreemption

C# controlling threads (resume/suspend)


I'm trying to simulate (very basic & simple) OS process manager subsystem, I have three "processes" (workers) writing something to console (this is an example):

    public class Message
    {
        public Message() { }
        public void Show()
        {
            while (true)
            {
                Console.WriteLine("Something");
                Thread.Sleep(100);
            }
        }
    }

Each worker is supposed to be run on a different thread. That's how I do it now: I have a Process class which constructor takes Action delegate and starts a thread from it and suspends it.

public class Process
{
    Thread thrd;
    Action act;

    public Process(Action act)
    {
        this.act = act;

        thrd = new Thread(new ThreadStart(this.act));
        thrd.Start();
        thrd.Suspend();
    }

    public void Suspend()
    {
        thrd.Suspend();
    }

    public void Resume()
    {
        thrd.Resume();
    }
}

In that state it waits before my scheduler resumes it, gives it a time slice to run, then suspends it again.

        public void Scheduler()
        {
            while (true)
            {
                //ProcessQueue is just FIFO queue for processes
                //MainQueue is FIFO queue for ProcessQueue's
                ProcessQueue currentQueue = mainQueue.Dequeue();
                int count = currentQueue.Count;

                if (currentQueue.Count > 0)
                {
                    while (count > 0)
                    {
                        Process currentProcess = currentQueue.GetNext();

                        currentProcess.Resume();
                        //this is the time slice given to the process
                        Thread.Sleep(1000);
                        currentProcess.Suspend();

                        Console.WriteLine();
                        currentQueue.Add(currentProcess);

                        count--;
                    }
                }

                mainQueue.Enqueue(currentQueue);
            }
        }

The problem is that it doesn't work consistently. It even doesn't work at all in this state, i have to add Thread.Sleep() before WriteLine in Show() method of the worker, like this.

        public void Show()
        {
            while (true)
            {
                Thread.Sleep(100); //Without this line code doesn't work
                Console.WriteLine("Something");
                Thread.Sleep(100);
            }
        }

I've been trying to use ManualResetEvent instead of suspend/resume, it works, but since that event is shared, all threads relying on it wake up simultaneously, while I need only one specific thread to be active at one time.

If some could help me figure out how to pause/resume task/thread normally, that'd be great. What I'm doing is trying to simulate simple preemptive multitasking. Thanks.


Solution

  • Thread.Suspend is evil. It is about as evil as Thread.Abort. Almost no code is safe in the presence of being paused at arbitrary, unpredictable locations. It might hold a lock that causes other threads to pause as well. You quickly run into deadlocks or unpredictable stalls in other parts of the system.

    Imagine you were accidentally pausing the static constructor of string. Now all code that wants to use a string is halted as well. Regex internally uses a locked cache. If you pause while this lock is taken all Regex related code might pause. These are just two egregious examples.

    Probably, suspending some code deep inside the Console class is having unintended consequences.

    I'm not sure what to recommend to you. This seems to be an academic exercise so thankfully this is not a production problem for you. User-mode waiting and cancellation must be cooperative in practice.