I am very inexperienced using multi-threading techniques, but here is what I have tried:
Thread thread = null;
for (int minute = 0; minute < 60; minute++)
{
Thread.Sleep(60000);
if (thread != null)
{
while (thread.ThreadState == ThreadState.Running) { }
}
thread = new Thread(delegate()
{
// Do stuff during the next minute whilst the main thread is sleeping.
});
thread.Start();
}
What I am trying to achieve here is to have a thread running and doing work whilst the main thread sleeps, but I am unsure why the above code doesn't work. What happens is that following the first loop (after starting the thread) the ThreadState doesn't seem to change from "Running". I am also curious as to whether there is a more elegant way of doing this.
Anyone know the problem?
Thread.Join is a better way to wait for a thread to end.
If you're using .Net 4, I'd recommend taking a look at the Task Class. It makes working with multithreading much easier/straight forward.
Using the Task class you can do this.
Task task = Task.Factory.StartNew(() =>
{
// Do stuff here.
});
task.Wait();
What you may be looking for is something more like this:
Thread thread = new Thread(delegate()
{
// Something that takes up to an hour
});
thread.Start();
for (int minute = 0; minute < 60; minute++)
{
Thread.Sleep(60000);
if (thread.IsAlive)
Console.WriteLine("Still going after {0} minute(s).", minute);
else
break; // Finished early!
}
// Check if it's still running
if (thread.IsAlive)
{
Console.WriteLine("Didn't finish after an hour, something may have screwed up!");
thread.Abort();
}
If this is what you're looking for, I'd take a look at the BackgroundWorker class.
Thread.Sleep(60000) is executed on the thread that calls it, in this case the main thread. Which is fine, but the "thread" doesn't know how long it has been running for and doesn't know when to actually stop. You need to have an object tell "thread" that it has been running for 60 seconds.
Thread thread = null;
for (int minute = 0; minute < 60; minute++)
{
if (thread != null)
{
while (thread.ThreadState == ThreadState.Running) { }
}
thread = new Thread(delegate()
{
try
{
// Do stuff during the next minute whilst the main thread is sleeping.
}
catch (ThreadAbortException ex)
{
}
});
thread.Start();
Thread.Sleep(60000);
thread.Abort();
}
This should achieve what you want but isn't really the most elegant way of stopping a thread. A thread should really be ended using callbacks.
Related
I am trying to end my Thread, within the thread, and when aborted, i want to detect that the thread has been aborted (or just, stopped really)
This is what i am doing to do that, but isnt working as it never gets to this part
if (!thread.IsAlive){
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
This is how i'm going about it, thank you for the help. sorry if my question is confusing please ask questions so i can help you help me :) thanks!
public static Thread thread;
public static void 1()
{
thread = new Thread(thread1);
thread.Start();
if (!thread.IsAlive)
{
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
public static void thread1()
{
{
int test = 0;
while (thread.IsAlive){
Console.WriteLine("running.."); // this text will be displayed when the thread is active, and will stop when stopped.
Thread.Sleep(2500);
test += 1;
if (test > 4) // after 4 loops, i want the thread to end itself
thread.Abort();
}
if (!thread.IsAlive){ // once the thread is ended i want it to tell us that, but it never gets to this part.
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
}
If you want to check if a thread is still alive, you cannot do that from the code running in that particular thread. Because, if you can execute the code to check if the thread is still alive, it is -- obviously -- still alive. And if the thread is not alive anymore it will -- obviously -- not be able to execute any more code ...
So the only way is to do this from somewhere outside the thread (ie some other thread, maybe even the main thread).
Just schematic code, which is rather clumsy, but will give you a first idea of how you can address this issue. But if there is a third party messing around with your threads, that won't help anything, because what prevents them from killing off your whole application?
public class ThreadTest {
static bool ranToEnd = false;
public static void Main(){
var thread = new Thread(aThread);
var lc = 1;
thread.Start();
while (true){
if (!aThread.IsAlive) {
if (ranToEnd)
Console.WriteLine("aThread terminated normally");
else
Console.WriteLine("aThread ended prematurely");
break;
} else if (++lc == 10) {
aThread.Abort(); //Simulating the abortion of the thread
}
Thread.Sleep(1000);
}
}
public static void aThread() {
//do some work in this thread
// if the thread ran to an end normally, this will be set to true
// if the thread ended prematurely, this will stay false ...
ranToEnd = true;
}
}
I am trying to do something with a timer in a loop and after the timer finishes its work, app starts another turn in the loop. But because I don't know how to ask the main thread stop running while timer is running, the main thread goes to the next turn immediately.
I did something about lock.
This is the loop
for (int i = 0; i < step; i++)
{
Monitor.Enter(locker);
//start timer
}
then the code inside of the timer
t_tick = (senders, args) =>
{
if (condition)
{
//do something
}
else
{
//do something
Monitor.Exit(AirplaneManager.locker);
t.Stop();
}
};
t.Tick += t_tick;
t.Interval = 30;
t.Start();
But this gives me an exception while the code runs into the monitor in timer : Object synchronization method was called from an unsynchronized block of code.
Is there any solution? Or I can use other way to reach my goal?
Thanks!
If you want the current thread to block for a set timespan, you can just use Thread.Sleep(TimeSpan)
https://msdn.microsoft.com/en-us/library/274eh01d(v=vs.110).aspx
You don't need to use another thread.
I am looking for a simple way to put a thread to sleep and to wake it. The thread runs in background in an infinite loop and sometimes does some work, sometimes just runs through. I have found out that there is no corresponding Wait() to the Sleep() and waking a thread with Interrupt() causes an exception. Apparently a sleeping thread is not meant to be disturbed.
Since I know when the work appears it seems a good idea to tell the thread, instead of having it check over and over again.
How can a thread be put to a 'lighter sleep' to be able to wake up alone each second or at a command from other thread?
//Thread to put to sleep and wake (thread1)
while (true)
{
if (thereIsWork)
{ DoWork(); }
//put thread to sleep in a way that other threads can wake it, and it wakes alone after some time (eg. 1000 ms)
// Thread.Sleep(1000); //nice, but not working as desired
}
-
//Other thread:
thereIsWork = true;
//thread1.Wake(); //Not existing
You can use an AutoResetEvent for this - just call Set() to signal work needs to be done and have your thread wait for it to be called using WaitOne().
This means the threads that are communicating this way share the same AutoResetEvent instance - you can pass it in as a dependency for the thread that does the actual work.
The thread shouldn't Sleep(), it should call WaitOne() on an AutoResetEvent or ManualResetEvent until some other thread calls Set() on that same resetevent object.
How about using a blocking queue, with Monitor Pulse and Wait:
class BlockingQueue<T>
{
private Queue<T> _queue = new Queue<T>();
public void Enqueue(T data)
{
if (data == null) throw new ArgumentNullException("data");
lock (_queue)
{
_queue.Enqueue(data);
Monitor.Pulse(_queue);
}
}
public T Dequeue()
{
lock (_queue)
{
while (_queue.Count == 0) Monitor.Wait(_queue);
return _queue.Dequeue();
}
}
}
Then thread 1 becomes
BlockingQueue<Action> _workQueue = new BlockingQueue<Action>();
while (true)
{
var workItem = _workQueue.Dequeue();
workItem();
}
And the other thread:
_workQueue.Enqueue(DoWork);
NB: you should probably use the built in type if you're using .Net 4 BlockingCollection using Add and Take instead of Enqueue and Dequeue.
Edit:
Ok. If you want it really simple...
//Thread to put to sleep and wake (thread1)
while (true)
{
lock(_lock)
{
while (!thereIsWork) Monitor.Wait(_lock);
DoWork();
}
//put thread to sleep in a way that other threads can wake it, and it wakes alone after some time (eg. 1000 ms)
// Thread.Sleep(1000); //nice, but not working as desired
}
and
//Other thread:
lock(_lock)
{
thereIsWork = true;
//thread1.Wake(); //Not existing
Monitor.Pulse(_lock);
}
I'n not an expert with threads, but maybe EventWaitHandle is what you're looking for. Check this link
In C# how does one achieve thread signaling?
Here is a custom-made console application example for you. Not really a good real world scenario, but the usage of thread signaling is there.
using System;
using System.Threading;
class Program
{
static void Main()
{
bool isCompleted = false;
int diceRollResult = 0;
// AutoResetEvent is one type of the WaitHandle that you can use for signaling purpose.
AutoResetEvent waitHandle = new AutoResetEvent(false);
Thread thread = new Thread(delegate() {
Random random = new Random();
int numberOfTimesToLoop = random.Next(1, 10);
for (int i = 0; i < numberOfTimesToLoop - 1; i++) {
diceRollResult = random.Next(1, 6);
// Signal the waiting thread so that it knows the result is ready.
waitHandle.Set();
// Sleep so that the waiting thread have enough time to get the result properly - no race condition.
Thread.Sleep(1000);
}
diceRollResult = random.Next(1, 6);
isCompleted = true;
// Signal the waiting thread so that it knows the result is ready.
waitHandle.Set();
});
thread.Start();
while (!isCompleted) {
// Wait for signal from the dice rolling thread.
waitHandle.WaitOne();
Console.WriteLine("Dice roll result: {0}", diceRollResult);
}
Console.Write("Dice roll completed. Press any key to quit...");
Console.ReadKey(true);
}
}
The way this works in a nutshell.
AutoResetEvent waitHandle = new AutoResetEvent(false); --- The false means that that wait handle is unsignaled if a waitHandle.WaitOne() is called it will stop the thread.
The thread you want to wait for another event to complete add
waitHandle.WaitOne();
In the thread that needs to be completed,at the end when completed add
waitHandle.Set();
waitHandle.WaitOne(); Waits for signal
waitHandle.Set(); signals completion.
For understanding concepts like signaling, see Thread Synchronization which would be a good place to start.
It's got examples too. You can then drill down into specific .net types based on what you're trying to do.. signal between threads within a process or across processes etc..
In my current C#/NET 3.5 application, I have a task queue (thread safe) and I have 5 worker threads that has to constantly look for tasks in the queue. If a task is available, any one worker will dequeue the task and take required action.
My worker thread class is as follows:
public class WorkerThread
{
//ConcurrentQueue is my implementation of thread safe queue
//Essentially just a wrapper around Queue<T> with synchronization locks
readonly ConcurrentQueue<CheckPrimeTask> mQ;
readonly Thread mWorker;
bool mStop;
public WorkerThread (ConcurrentQueue<CheckPrimeTask> aQ) {
mQ = aQ;
mWorker = new Thread (Work) {IsBackground = true};
mStop = false;
}
private void Work () {
while (!mStop) {
if (mQ.Count == 0) {
Thread.Sleep (0);
continue;
}
var task = mQ.Dequeue ();
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;
task.IsPrime = IsPrime (task.Number);
task.ExecutedBy = Thread.CurrentThread.ManagedThreadId;
//Ask the threadpool to execute the task callback to
//notify completion
ThreadPool.QueueUserWorkItem (task.CallBack, task);
}
}
private bool IsPrime (int number) {
int limit = Convert.ToInt32 (Math.Sqrt (number));
for (int i = 2; i <= limit; i++) {
if (number % i == 0)
return false;
}
return true;
}
public void Start () {
mStop = false;
mWorker.Start ();
}
public void Stop () {
mStop = true;
}
}
Problem is that when queue is empty, it consumes too much CPU (nearly 98%). I tried AutoResetEvent to notify the workers that queue has been changed. So they effectively wait for that signal to set. It has braught down the CPU to nearly 0% but I am not entirely sure whether this is the best method. Can you suggest a better method to keep the threads idle without hurting CPU usage?
Check out this implementation of a BlockingQueue. If the queue is empty, it uses Monitor.Wait() to put the thread to sleep. When an item is added, it uses Monitor.Pulse() to wake up a thread that is sleeping on the empty queue.
Another technique is to use a semaphore. Each time you add an item to a queue, call Release(). When you want an item from a queue, call WaitOne().
You currently have Thread.Sleep(0) in your Work method for where there are no queue items. Change it to anything greater than 0 and your CPU use will go down. Try 10 to start with...
You have a couple of options that I can think of.
One way is to place a small thread sleep during your loop. This will basically drop your CPU usage to 0 and is fairly standard way of doing this.
Another way is to use a reset (either auto or manual) as suggested by Mitch Wheat in the comments.
You could also devise some kind of IdleTask that has a thread sleep for a certain amount of time and if your queue is empty, just process the IdleTask (which will thread sleep).
If your Queue is thread safe then you would not need to do this...
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;