Muhammad Hassan
Muhammad Hassan

Reputation: 1304

Pause And Resume A Thread From Another Thread In C#

I am running two functions in threading. One have a loop and second one is waiting for an input so when the input occurs then it should pause the first loop thread and ask in the same second thread to resume or kill the thread...???

You can see my code below where I want to implement this logic...

class Program
    {
        public static int flag = 0;
        public static int process;
        public static int quantum;
        public static int[] execTime = new int[10];
        public static string[] P0 = new string[100];
        public static string[] P1 = new string[100];
        public static string[] P2 = new string[100];
        public static string[] P3 = new string[100];
        public static string[] P4 = new string[100];
        public static string[] P5 = new string[100];
        public static string[] P6 = new string[100];
        public static string[] P7 = new string[100];
        public static string[] P8 = new string[100];
        public static string[] P9 = new string[100];
        public static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This         
            //************************//
            //*** Filling Process ***//
            //************************//
            for (int i = 0; i < P0.Length; i++)
            {
                P0[i] = "P0." + i;                
            }
            for (int i = 0; i < P1.Length; i++)
            {
                P1[i] = "P1." + i;
            }
            for (int i = 0; i < P2.Length; i++)
            {
                P2[i] = "P2." + i;
            }
            for (int i = 0; i < P3.Length; i++)
            {
                P3[i] = "P3." + i;
            }
            for (int i = 0; i < P4.Length; i++)
            {
                P4[i] = "P4." + i;
            }
            for (int i = 0; i < P5.Length; i++)
            {
                P5[i] = "P5." + i;
            }
            for (int i = 0; i < P6.Length; i++)
            {
                P6[i] = "P6." + i;
            }
            for (int i = 0; i < P7.Length; i++)
            {
                P7[i] = "P7." + i;
            }
            for (int i = 0; i < P8.Length; i++)
            {
                P8[i] = "P8." + i;
            }
            for (int i = 0; i < P9.Length; i++)
            {
                P9[i] = "P9." + i;
            }

            //************************//
            //*** Creating Process ***//
            //************************//
            do
            {
                Console.Write("How Many Process You Want To Create? (0-10) ");
                process = Convert.ToInt16(Console.ReadLine());
                if (process > 10)
                {
                    Console.ForegroundColor = ConsoleColor.Red; // Red Color Text Below This
                    Console.WriteLine("Error => Your Process Should Be Less Then 10.");
                    Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This
                }
            } while (process > 10);
            Console.ForegroundColor = ConsoleColor.Green; // Green Color Text Below This
            Console.WriteLine("Success =>" + process + " Process Have Been Generated.");
            Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This

            //***************************************//
            //*** Creating Process Executing TIme ***//
            //***************************************//
            for (int i = 0; i < process; i++)
            {                
                do
                {
                    Console.Write("What\'s The Executing Time Your Process # " + i + "? (0-100) ");
                    execTime[i] = Convert.ToInt16(Console.ReadLine());
                    if (execTime[i] > 100)
                    {
                        Console.ForegroundColor = ConsoleColor.Red; // Red Color Text Below This
                        Console.WriteLine("Error => Your Executing Time Should Be Less Then 100.");
                        Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This
                    }
                } while (execTime[i] > 100);
            }
            Console.ForegroundColor = ConsoleColor.Green; // Green Color Text Below This
            Console.WriteLine("Success =>" + process + " Executing Time Have Been Generated.");
            Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This

            //**************************************//
            //*** Resizing Process Array's Steps ***//
            //**************************************//
            Array.Resize(ref P0, execTime[0]);
            Array.Resize(ref P1, execTime[1]);
            Array.Resize(ref P2, execTime[2]);
            Array.Resize(ref P3, execTime[3]);
            Array.Resize(ref P4, execTime[4]);
            Array.Resize(ref P5, execTime[5]);
            Array.Resize(ref P6, execTime[6]);
            Array.Resize(ref P7, execTime[7]);
            Array.Resize(ref P8, execTime[8]);
            Array.Resize(ref P9, execTime[9]);
            Array.Resize(ref P0, execTime[0]);

            //********************//
            //*** Quantum Size ***//
            //********************//
            do
            {
                Console.Write("What's Your Quantum Size? ");
                quantum = Convert.ToInt16(Console.ReadLine());
                if (quantum > execTime.Sum())
                {
                    Console.ForegroundColor = ConsoleColor.Red; // Red Color Text Below This
                    Console.WriteLine("Error => Your Quantum Size Should Be Less Then Total Execution Time.");
                    Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This
                }
            } while (quantum > execTime.Sum());
            Console.ForegroundColor = ConsoleColor.Green; // Green Color Text Below This
            Console.WriteLine("Success =>" + quantum + " Quantum Size Have Been Generated.");
            Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This

            Thread obj1 = new Thread(processRunning);
            Thread obj2 = new Thread(interrupt);
            obj1.Start();   // Start This Thread
            obj2.Start();    // Start This Thread

        }

        static public void processRunning()
        {
            //***********************//
            //*** Running Process ***//
            //***********************//

            Console.ForegroundColor = ConsoleColor.Green; // Green Color Text Below This
            Console.WriteLine("Process Has Been Started Running...!!!");
            Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This

            int i = 0;
            while (i < execTime.Sum())
            {
                if (i < P0.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 0");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P0.Length)
                        {
                            Console.WriteLine(P0[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }                
                if (i < P1.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 1");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P1.Length)
                        {
                            Console.WriteLine(P1[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P2.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 2");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P2.Length)
                        {
                            Console.WriteLine(P2[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P3.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 3");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P3.Length)
                        {
                            Console.WriteLine(P3[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P4.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 4");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P4.Length)
                        {
                            Console.WriteLine(P4[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P5.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 5");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P5.Length)
                        {
                            Console.WriteLine(P5[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P6.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 6");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P6.Length)
                        {
                            Console.WriteLine(P6[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P7.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 7");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P7.Length)
                        {
                            Console.WriteLine(P7[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P8.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 8");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P8.Length)
                        {
                            Console.WriteLine(P8[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                if (i < P9.Length)
                {
                    Thread.Sleep(1000);
                    int j;
                    Console.WriteLine("----------------------------------------");
                    Console.WriteLine("Process Identification ID : Process # 9");
                    for (j = i; j < i + quantum; j++)
                    {
                        if (j < P9.Length)
                        {
                            Console.WriteLine(P9[j]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    Console.WriteLine("IR --> " + i);
                    Console.WriteLine("PC --> " + i);
                    Console.WriteLine("Flag --> " + flag);
                    Console.WriteLine("Last Instruction Address --> " + (j - 1));
                    Console.WriteLine("Resume Instruction Address --> " + j);
                    Console.WriteLine("Algorithum --> Round Robin");
                    Console.WriteLine("Quantum --> " + quantum);
                    Console.WriteLine("----------------------------------------");
                }
                // Increment
                i = i + quantum;
            }

            Console.ForegroundColor = ConsoleColor.Green; // Green Color Text Below This
            Console.WriteLine("Process Has Been Completed Running...!!!");
            Console.ForegroundColor = ConsoleColor.White; // White Color Text Below This
            Console.ReadLine();
        }
        static public void interrupt()
        {
            // Intruppt
            ConsoleKeyInfo c = Console.ReadKey();
            if (c.Key == ConsoleKey.Enter)
            {
                flag = 1;
                // Should Pause The First Thread Here And Ask To Continue/Resume Or Kill
            }
            // Intruppt
        }
    }

Here I want to keep running processRunning(); untill someone give input to interrupt(); and then it should pause processRunning(); and wait for resume that will be also allowed by interrupt(); function so what should be the logic/code behind it...???

Upvotes: 2

Views: 5076

Answers (3)

MIHOW
MIHOW

Reputation: 411

Here's simpler version of Tamas Ionut's answer.
Thread Interrupt is constantly checking User input, when it gets Enter Key, the volatile interupt flag is set to True, and because of that Thread Process gets blocked by usage of signal.WaitOne().
By pressing f the signal is being Set, so the Process Thread gets unblocked.

    private static AutoResetEvent signal = new AutoResetEvent(false);
    private volatile static bool interruptFlag;

    private static uint counter = 0;

    static void Main(string[] args)
    {
        Thread process = new Thread(Process);
        process.Start();

        Thread interrupt = new Thread(Interrupt);
        interrupt.Start();
    }

    private static void Process()
    {
        //replace true with your condition
        while (true)
        {
            if (interruptFlag)
            {
                Console.WriteLine("not doing work");
                Console.WriteLine("press F to do work again");

                counter = 0;

                if (signal.WaitOne())
                {
                    Console.WriteLine();
                }
            }

            Console.WriteLine(string.Concat("doing work ", (counter++).ToString()));

            Task.Delay(200).Wait();

            //.. important work here
        }
    }

    private static void Interrupt()
    {
        while (true)
        {
            ConsoleKeyInfo c = Console.ReadKey();
            if (c.Key == ConsoleKey.Enter)
            {
                interruptFlag = true;
                
                c = Console.ReadKey();

                if(c.Key == ConsoleKey.F)
                {
                    interruptFlag = false;
                    signal.Set();
                }
            }
        }
    }

Upvotes: 1

Tamas Ionut
Tamas Ionut

Reputation: 4410

There are a couple of things that you should have in mind here:

  1. It exists a Thread.Suspend mechanism described here but it is obsolete and for a good reason, since:

Because Thread.Suspend and Thread.Resume do not rely on the cooperation of the thread being controlled, they are highly intrusive and can result in serious application problems like deadlocks (for example, if you suspend a thread that holds a resource that another thread will need).

So you could use that mechanism and wait and see possible deadlocks or other synchronization bugs or:

  1. You could move that synchronization logic into the thread that you want to suspend, the processRunning() method in your case and do something like this:

    while (i < execTime.Sum() && flag==0) //not stopped yet

If you want finer granularity, that is even stopping in the middle of the loop not at each iteration, it is your job to add more checks as you please.

You also need to declare your flag as volatile since that field is used by two threads and needs to be marked as such:

public static volatile int flag = 0;

This is a simplified example:

    private static AutoResetEvent signal = new AutoResetEvent(false);
    private volatile static bool interruptFlag;
    private volatile static bool abortFlag;

    private static void Process()
    {
        //replace true with your condition
        while (true)
        {
            if (interruptFlag)
            {
                if (signal.WaitOne())
                {
                    if (abortFlag)
                    {
                        Console.WriteLine("exiting");
                        return;
                    }
                }
            }

            Console.WriteLine("doing work");

            //.. important work here
        } 
    }

    private static void Interrupt() {
        ConsoleKeyInfo c = Console.ReadKey();
        if (c.Key == ConsoleKey.Enter) {
            interruptFlag = true;
            // Should Pause The First Thread Here And Ask To Continue/Resume Or Kill

            c = Console.ReadKey();

            if (c.Key == ConsoleKey.Escape)
            {
                Console.WriteLine("Interrupting");
                abortFlag = true;
                signal.Set();
            }
            else
            {
                Console.WriteLine("Continuing");
                interruptFlag = false;
                abortFlag = false;
                signal.Set();
            }
        }
    }

    static void Main()
    {
        Thread process = new Thread(Process);
        process.Start();

        Thread interrupt = new Thread(Interrupt);
        interrupt.Start();

    }

Upvotes: 3

Jace
Jace

Reputation: 817

Try using a BackgroundWorker object(System.ComponentModel)

BackgroundWorker obj1 = new BackgroundWorker();
obj1.DoWork += (dowork_s, dowork_e) => {
    ProcessRunning();
};
obj1.RunWorkerCompleted += (completed_s, completed_e) => {
    Thread.Sleep(1000);
    if(StillRunning){
        worker.RunWorkerAsync();
    }
    //if not still running, the thread will now terminate
};

You may pause the execution of the thread by invoking obj1.Reset(), and resume via obj1.Set().

Upvotes: -1

Related Questions