C# 使用手动重置事件启动停止线程



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

我想了解如何用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();
        }
    }
}

当我运行程序时,线程已取消启动:

线程状态:未启动 输入命令行(启动/等待/设置/状态/退出(

启动线程后,事情变得奇怪。ThreadState立即从"正在运行"更改为"等待睡眠加入"。这是什么原因呢?我以为线程将保持其运行状态,直到我们将该方法称为 WaitOne() .

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

线程状态:未启动 输入命令行(启动/等待/设置/状态/退出( 开始 线程状态:正在运行 输入命令行(启动/等待/设置/状态/退出( 这个引擎正在努力工作!! 地位>运行

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

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

Engine.ThreadHandle.WaitOne(Timeout.Infinite);

线程保持运行:

线程状态:未启动 输入命令行(启动/等待/设置/状态/退出( 开始 线程状态:正在运行 输入命令行(启动/等待/设置/状态/退出( 这个引擎正在努力工作!! 地位>跑步 线程状态:正在运行 输入命令行(启动/等待/设置/状态/退出( 这个引擎正在努力工作!! 等 线程状态:运行

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

我的问题仍然是:

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

你的WaitOne()永远不会工作,因为它在主循环中,而代码执行在后面(两个for循环(。
您需要将其向下移动:

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

最新更新