使用ManualResetEvent

时间:2018-08-08 08:54:58

标签: c# multithreading resume manualresetevent

编辑:我从.Sleep(5000)方法中删除了Run(),并用模拟复杂计算的双循环替换了它。

我想了解如何使用ManualResetEvent控制线程? 我写了应该启动,停止和恢复前台线程的那段简单代码,但是它没有按预期工作。

using System;
using System.Threading;

namespace ThreadHandler
{
    public class Engine
    {
        public static ManualResetEvent ThreadHandle;
        public static void Run()
        {
            Random rng = new Random();
            ThreadHandle = new ManualResetEvent(true);
            while (true)
            {
                ThreadHandle.WaitOne();
                for (int i = Int32.MaxValue; i > 0; i--)
                {
                    for (int j = 0; j < rng.Next(); j++)
                    {
                        int res;
                        int div =    
Math.DivRem(Math.Abs(Convert.ToInt32(Math.Floor(Math.Log(rng.NextDouble()) / 
Math.Log(rng.NextDouble())))),                           
Math.Abs(Convert.ToInt32(Math.Floor(Math.Log(rng.NextDouble()) /Math.Log(rng.NextDouble())))) + 1, out res);
                        double calc = Math.Sin(Math.Sqrt(div)) * Math.Cos(Math.Sqrt(res));
                    }
                    if (i % 500 == 0)
                        Console.WriteLine("This engine is working hard!!!");
                }
            }
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Thread engine = new Thread(Engine.Run);
            int cnt = 100;
            while (cnt-- > 0)
            {
                Console.WriteLine("\nThread status: " +  engine.ThreadState);
                Console.WriteLine("Enter command line (Start/Wait/Set/Status/Quit)");
                string cmd = Console.ReadLine();
                switch(cmd.ToUpper())
                {
                    case "START":
                        engine.Start();
                        break;
                    case "WAIT":
                        Engine.ThreadHandle.WaitOne(Timeout.Infinite);
                        break;
                    case "SET":
                        Engine.ThreadHandle.Set();
                        break;
                    case "STATUS":
                        Console.WriteLine("  >" + engine.ThreadState);
                        break;
                    case "QUIT":
                        cnt = 0;
                        break;
                    default:
                        Console.WriteLine("Unknown command");
                        break;
                }
            }
            engine.Abort();
        }
    }
}

运行程序时,线程未启动:

    Thread status: Unstarted
    Enter command line (Start/Wait/Set/Status/Quit)

启动线程后,事情变得很奇怪。 ThreadState立即从运行更改为WaitSleepJoin。是什么原因呢?我以为线程将保持其运行状态,直到我们调用方法WaitOne()

编辑:线程启动,其ThreadState在逻辑上为Running

Thread status: Unstarted
Enter command line (Start/Wait/Set/Status/Quit)
start

Thread status: Running
Enter command line (Start/Wait/Set/Status/Quit)
This engine is working hard!!!
status
  >Running

然后,当我输入Wait时,线程停留在WaitSleepJoin中,但是引擎继续运行。

编辑:我现在遇到的问题是如何停止它?当我打电话

Engine.ThreadHandle.WaitOne(Timeout.Infinite);

线程继续运行:

Thread status: Unstarted
Enter command line (Start/Wait/Set/Status/Quit)
start

Thread status: Running
Enter command line (Start/Wait/Set/Status/Quit)
This engine is working hard!!!
status
  >Running

Thread status: Running
Enter command line (Start/Wait/Set/Status/Quit)
This engine is working hard!!!
wait

Thread status: Running

最后,当我键入Set时,线程永远不会回到运行状态。

我的问题仍然是:

  1. 如何中断调用方法Engine的线程WaitOne()托架?
  2. 之后如何恢复?

1 个答案:

答案 0 :(得分:0)

在执行代码(两个for循环)之后,您的WaitOne()将永远不会像在主循环中那样工作。
您需要将其向下移动:

while (true)
{
    for (int i = Int32.MaxValue; i > 0; i--)
    {
        for (int j = 0; j < rng.Next(); j++)
        {
            ThreadHandle.WaitOne();
            // ...
        }

        if (i % 500 == 0)
            Console.WriteLine("This engine is working hard!!!");
    }
}

结果

Thread status: WaitSleepJoin
Enter command line (Start/Wait/Set/Status/Quit)

注意
我相信您会误用ManualResetEvent,因为WaitOne方法需要等待的人(在您的情况下为Thread)调用,但您要两次调用它。您可能应该使用布尔值来向线程发送信号,通知它应该启动WaitOne