在C#中暂停并恢复来自另一个线程的线程

时间:2016-03-28 16:08:47

标签: c# .net multithreading

我在线程中运行两个函数。一个有一个循环而第二个正在等待输入,所以当输入发生时它应该暂停第一个循环线程并要求在同一个第二个线程中恢复或终止线程...... ???

您可以在下面的代码中看到我想要实现此逻辑的代码......

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

在这里,我希望继续运行processRunning();,直到有人向interrupt();提供输入,然后它应暂停processRunning();并等待interrupt();功能也允许的恢复那么它背后的逻辑/代码应该是什么...... ???

3 个答案:

答案 0 :(得分:1)

您应该记住以下几点:

  1. 它存在一个描述here的Thread.Suspend机制,但它已经过时,并且有充分的理由,因为:
  2.   

    因为Thread.Suspend和Thread.Resume不依赖于被控制的线程的协作,所以它们是高度侵入性的并且可能导致严重的应用程序问题,例如死锁(例如,如果你挂起一个拥有资源的线程,另一个线程需要)。

    因此,您可以使用该机制并等待并查看可能的死锁或其他同步错误或:

    1. 您可以将同步逻辑移动到要挂起的线程中,在您的情况下使用processRunning()方法并执行以下操作:

      while(i&lt; execTime.Sum()&amp;&amp; flag == 0)//尚未停止

    2. 如果你想要更精细的粒度,甚至在循环中停止而不是每次迭代,你可以随意添加更多的支票。

      您还需要将您的标志声明为volatile,因为该字段由两个线程使用,需要标记为:

      public static volatile int flag = 0;

      这是一个简化的例子:

          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();
      
          }
      

答案 1 :(得分:1)

这是 Tamas Ionut 答案的更简单版本。
线程中断不断检查用户输入,当它获得 Enter 键时,易失性中断标志设置为 True,因此线程进程被使用 signal.WaitOne() 阻塞。
按 f 信号是被设置,所以进程线程被解除阻塞。

class MyView(View):
    template_name = f'{APP_NAME}/{TEMPLATE_NAME}'
    ...
    def get(self, request, *args, **kwargs)
        return render(
            request,
            'app/helloworld.html',
            {
                'title_test': hello_title,
                'template_name': self.template_name
            }
        )

答案 2 :(得分:-1)

尝试使用BackgroundWorker对象(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
};

您可以通过调用obj1.Reset()暂停执行该线程,并通过obj1.Set()恢复。