简体   繁体   中英

C# Start Stop Thread with ManualResetEvent

Edit: I have removed .Sleep(5000) from the Run() method and replaced that with a double loops that simulate complex calculations.

I would like to understand how to control a Thread with ManualResetEvent ? I wrote that simple piece of code which is supposed to start, stop and resume a foreground Thread but it does not work as expected.

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

When I run the program, the Thread is unstarted:

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

After starting the Thread, things gets weird. The ThreadState immediately changes from Running to WaitSleepJoin. What is the reason for that? I thought the Thread would remain in its Running state until we call the method WaitOne() .

Edit: The Thread starts and its ThreadState is logically 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

Then when I type in Wait, the Thread stays in WaitSleepJoin, but the Engine keeps on running.

Edit: The problem I now have is how can I stop it? When I call

Engine.ThreadHandle.WaitOne(Timeout.Infinite);

The Thread keeps 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

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

Thread status: Running

Finally when I type in Set, the Thread never go back to Running state.

My questions remains are:

  1. How can I interrupt the Thread Engine bay calling the method WaitOne() ?
  2. How can I resume it after?

Your WaitOne() will never work as it's in the main loop while the code executing is after (the two for loops).
You need to move it down:

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!!!");
    }
}

Result

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

Note
I believe that you're miss-using ManualResetEvent as the WaitOne method needs to be called by who's gonna wait (the Thread in your case) but you're calling it twice. You should probably use a boolean to signal to the thread that it should start the WaitOne rather.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM