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.
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.