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:
Engine
bay calling the method WaitOne()
? 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.