Previously, I ran a method in a thread like this:
static void procedure() { while (x) thread.sleep() }
static Thread runner;
...
void method(){
runner = new Thread(new ThreadStart(procedure));
runner.Start();
}
I changed this in an attempt to have a single thread that I can start at different points.
static void procedure() { while (x) thread.sleep() }
static Thread runner;
void main(){
runner = new Thread(new ThreadStart(procedure));
...
}
...
void method(){
runner.Start();
}
This no longer runs the thread as expected. The program halts, which I believe is due to the new thread running on the main thread.
Why is it no longer running on a seperate thread?
Works fine, here's an example based on your code.
class Program
{
static void procedure()
{
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("Sleep");
}
}
static Thread runner;
static void Main(string[] args)
{
runner = new Thread(new ThreadStart(procedure));
Console.WriteLine("Here!");
runner.Start();
Console.WriteLine("And now here...");
}
}
Related
I have the below code and certainly I have a deadlock using Threads, but why not happens with tasks?
private static object lockObject1 = new object();
private static object lockObject2 = new object();
static void Main(string[] args)
{
Console.Title = "Deadlocks";
//Using tasks.
Task ourTask1 = new Task(SingleMethod_A);
ourTask1.Start();
Task ourTask2 = new Task(SingleMethod_B);
ourTask2.Start();
//Using threads.
//Thread ourThread1 = new Thread(new ThreadStart(SingleMethod_A));
//Thread ourThread2 = new Thread(new ThreadStart(SingleMethod_B));
//ourThread1.Start();
//ourThread2.Start();
Console.WriteLine("Deadlock");
}
public static void SingleMethod_A()
{
lock (lockObject1)
{
Thread.Sleep(1000);
lock (lockObject2)
{
Console.WriteLine("not possible.");
}
}
}
public static void SingleMethod_B()
{
lock (lockObject2)
{
Thread.Sleep(1000);
lock (lockObject1)
{
Console.WriteLine("not possible.");
}
}
}
Tasks can certainly dead lock. It is also important to keep in mind that Tasks aren't threads - they may run on one from the thread pool.
Why you aren't seeing it is because your case is a trivial example and .Start doesn't have to use separate threads. Try changing your calls to start to Task.Run(action) instead to see the deadlock:
Task.Run(() => SingleMethod_A());
Task.Run(() => SingleMethod_B());
When Thread.Abort() is called, and that thread is executing finally block, then thread won't abort until finally block is finished. But, as i see, ThreadAbortException is generated not right after the end of finally block, but after some delay:
private static volatile int val1 = 0;
public static void Func1()
{
try
{
}
finally
{
Thread.Sleep(5000);
}
//Func2();
while (true)
val1++;
}
public static void Main()
{
var thread = new Thread(Func1);
thread.Start();
Thread.Sleep(1000);
thread.Abort();
thread.Join();
Console.WriteLine(val1); // val1 is non-zero!
}
In this example, val1 at the end of Main() will be non-zero. Why does it happen?
If i uncomment call to Func2() (Func2 is any method, possibly empty), output for val1 will show "0". Why does adding of method affect point of thread abortion?
In this case it could be usefull to surround the increment with a lock. The lock controlls the access on that member. The Abort method just notify the thread "Hey, you can stop now" but it does not kill the Thread. So the thread can be alive for a few moments after the Abort. Accessing the lock the thread checks if it got aborted and kills it self if needed.
Here is your example code edited
using System;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
private static volatile int val1 = 0;
static Object Locker = new Object();
public static void Func1()
{
try
{
}
finally
{
Thread.Sleep(5000);
}
//Func2();
while (true)
{
//Lock the access to the member
lock (Locker)
val1++;
}
}
public static void Main()
{
var thread = new Thread(Func1);
thread.Start();
Thread.Sleep(1000);
//Not needed. Just to make sure
lock (Locker)
{
thread.Abort();
thread.Join();
}
Console.WriteLine(val1); // val1 is non-zero!
// Now it is zero
Console.ReadLine();
}
}
}
Sorry for late answer
I'm having trouble understanding why my console app doesn't wait until the thread it spawns fully terminates. I think this is related to the fact that the thread in question also spawns its own child threads and/or the inclusion of System.Timer
The basic program flow is as follows. Main creates a new thread against the Simulator.Start method, and then joins until that thread terminates. Simulator.Start creates a new Timer (to constrain how long it should execute) and then creates/runs a bunch of child threads. When the Elapsed event is raised by the Timer, this signals that the Simulator should terminate all of its child threads and generate a report. The problem is that the console app exits as soon as all child threads terminate and the code to generate a report never gets executed (See Simulator.Stop method below).
Hopefully some pseudo code will help:
public class Program
{
private static Simulator _simulator;
private static void Main(string[] args)
{
var options = new SimulationOptions();
//check for valid options
if (!Parser.Default.ParseArguments(args, options)) return;
_simulator = new Simulator(options);
var thread = new Thread(_simulator.Start) {IsBackground = false};
thread.Start();
thread.Join();
}
}
public class Simulator
{
private readonly SimulationOptions _options;
private readonly List<Thread> _threads = new List<Thread>();
private readonly List<Worker> _workers = new List<Worker>();
private static Timer _timer;
public Simulator(SimulationOptions options)
{
_options = options;
StartTimer(_options.LengthOfTest);
}
private void StartTimer(int lengthOfTest)
{
_timer = new Timer {Interval = lengthOfTest*1000};
_timer.Elapsed += Timer_Elapsed;
_timer.Start();
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
_timer.Stop();
Stop();
}
public void Stop()
{
// Request that the worker thread stop itself:
foreach (Worker worker in _workers)
{
worker.RequestStop();
}
GenerateReport(); //<-- this code never gets executed
}
private XDocument GenerateReport()
{
//build an awesome report
}
public void Start()
{
_threads.Clear();
_workers.Clear();
for (int i = 0; i < _options.NumberOfClients; i++)
{
_workers.Add(new Worker());
_threads.Add(new Thread(_workers.Last().PumpMessages));
_threads.Last().Start();
}
}
}
public class Worker
{
private bool _shouldStop = false;
public void PumpMessages()
{
while (!_shouldStop)
{
//does cool stuff until told to stop
}
}
public void RequestStop()
{
_shouldStop = true;
}
}
Nothing in your start method keeps the thread alive. When the following method finishes, so does the thread. You then call Thread.Join and that is the end of that.
public void Start()
{
_threads.Clear();
_workers.Clear();
for (int i = 0; i < _options.NumberOfClients; i++)
{
_workers.Add(new Worker());
_threads.Add(new Thread(_workers.Last().PumpMessages));
_threads.Last().Start();
}
}
If you intend on waiting for this work to complete, consider waiting on a ManualResetEvent for each worker thread that you are using.
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx
http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitall.aspx
Your method should look something like the following.
public void Start()
{
_threads.Clear();
_workers.Clear();
var evts = new List<ManualResetEvent>()
for (int i = 0; i < _options.NumberOfClients; i++)
{
ManualResetEvent evt = new ManualResetEvent(false);
evts.Add(evt);
_workers.Add(new Worker(evt));
_threads.Add(new Thread(_workers.Last().PumpMessages));
_threads.Last().Start();
}
WaitHandle.WaitAll(evts.ToArray());
}
public class Worker
{
private bool _shouldStop = false;
private readonly ManualResetEvent #event;
public Worker(ManualResetEvent #event)
{
this.#event = #event;
}
public void PumpMessages()
{
while (!_shouldStop)
{
//does cool stuff until told to stop
}
#event.Set();
}
public void RequestStop()
{
_shouldStop = true;
}
}
Join method waits only for thread instance you joined, so Simulator.Start just creates some threads and it terminates, as the result Join returns and your main thread terminates. But still your App is alive(reason some other Foreground threads are still running).
generate a report never gets executed? Why?
Process will terminate when all Foreground Threads terminates. so as soon as your child threads return from PumpMessages method when you call RequestStop in a loop, all of your foreground threads terminates
public void Stop()
{
// Request that the worker thread stop itself:
foreach (Worker worker in _workers)
{
worker.RequestStop();
}
<--here all foreground threads are ready to terminate
GenerateReport(); //<-- this code never gets executed
}
It was little misleading that I stated that all foreground threads die after the loop. To make it clear let's say that we have given instruction for the worker threads to stop working, so all threads may or may not die before executing GenerateReport method. yes there is a Race If worker threads wins the race then we lose it, and viceversa. sometimes your GenerateReport may execute without any problem.
How to fix it? We just wait for all our worker threads to terminate. that's it.
public void Start()
{
_threads.Clear();
_workers.Clear();
for (int i = 0; i < _options.NumberOfClients; i++)
{
_workers.Add(new Worker());
_threads.Add(new Thread(_workers.Last().PumpMessages));
_threads.Last().Start();
}
foreach (var t in _threads)
t.Join();
}
I am making an application in C# which uses a winform as the GUI and a separate thread which is running in the background automatically changing things. Ex:
public void Run()
{
while(true)
{
printMessageOnGui("Hey");
Thread.Sleep(2000);
// Do more work
}
}
How would I make it pause anywhere in the loop, because one iteration of the loop takes around 30 seconds. So I wouldn't want to pause it after its done one loop, I want to pause it on time.
var mrse = new ManualResetEvent(false);
public void Run()
{
while (true)
{
mrse.WaitOne();
printMessageOnGui("Hey");
Thread.Sleep(2000); . .
}
}
public void Resume() => mrse.Set();
public void Pause() => mrse.Reset();
You should do this via a ManualResetEvent.
ManualResetEvent mre = new ManualResetEvent();
mre.WaitOne(); // This will wait
On another thread, obviously you'll need a reference to the mre
mre.Set(); // Tells the other thread to go again
A full example which will print some text, wait for another thread to do something and then resume:
class Program
{
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(SleepAndSet));
t.Start();
Console.WriteLine("Waiting");
mre.WaitOne();
Console.WriteLine("Resuming");
}
public static void SleepAndSet()
{
Thread.Sleep(2000);
mre.Set();
}
}
You can pause a thread by calling thread.Suspend but that is deprecated. I would take a look at autoresetevent for performing your synchronization.
I have a console app that I want to run continually in the background. I thought that if I started it up and then told it to wait things would work. But when I have it wait, it freezes the application.
Here is my code:
class Program
{
static public ManualResetEvent StopMain;
static void Main(string[] args)
{
// Hide the cursor.
Cursor.Current = Cursors.Default;
StopMain = new ManualResetEvent(false);
RunHook runHook = new RunHook();
// wait until signalled by Program.StopMain.Set();
StopMain.WaitOne();
}
}
class RunHook
{
private HookKeys hook;
public RunHook()
{
hook = new HookKeys();
hook.HookEvent += EventForHook;
}
private void EventForHook(HookEventArgs e, KeyBoardInfo keyBoardInfo,
ref Boolean handled)
{
if ((keyBoardInfo.scanCode == 4) && (keyBoardInfo.vkCode == 114))
handled = true;
}
}
Any ideas on how to have this run in the background but never terminate?
The behavior you see is expected. You have one thread, and it's in a wait state. To get some form of activity, you have to let the scheduler actually do something. A background thread is one way to achieve this:
static void Main(string[] args)
{
StopMain = new ManualResetEvent(false);
bool exit = false;
new Thread(
delegate
{
new RunHook();
while(!exit) { Thread.Sleep(1); }
}
).Start();
StopMain.WaitOne();
exit = true;
}
Another is to just let the primary thread yield:
static void Main(string[] args)
{
StopMain = new ManualResetEvent(false);
RunHook runHook = new RunHook();
while(!StopMain.WaitOne())
{
Thread.Sleep(1);
}
}
There are certainly other ways, too. Personally I'd do neither of these. Instead I'd add a blocking method to the RunHook class and have it return when it was done or signalled.