I have an multithreaded application and I want to be able to use a timer to periodically check to see if all threads have finished before starting a new one, ie:
var checkStatusTimer = new System.Threading.Timer(new TimerCallback(CheckThreads), null, 10000, 10000);
This is as far as I've come. What would need to go in the CheckThreads Method to check to see if they're done? I was thinking of something along the lines of a function that checks them like:
foreach (Thread thread in Threads)
{
Thread t = thread;
if (t.ThreadState != ThreadState.Stopped)
return false;
}
Am I on the right track? is this the correct way to go about this? Or should I use a System.Timers.Timer instead? Also, the function form within I want to do this periodic check is static. Any help would be appreciated.
Use Task instead of Thread. Then, you can create a combined task:
Task[] tasks = ...; //You provide this
Task combined = Task.WhenAll(tasks);
Now you can check for completion: combined.IsCompleted. You can also Wait and await that task.
Thread is a legacy API that is rarely a good idea to use.
#usr's task-based approach is best, but if you must rely on threads, then I suggest that as each thread is completes it invokes a method that removes the thread from your Threads collection. Then all you have to do in your timer callback is to check the count of the collection. Relying on ThreadState is not advisable.
Related
So I'm still fairly new to C#.
So far I would like to know how to check if a thread has ended. I know that i can put a bool at the end of the method the thread uses and use that to determine if the thread ends.. but i dont want to do that, mainly because i want to learn the right way
so far I have this.
Thread testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
I read about the thread.join(); class. To my understanding, that class only prevents any code after that from executing.. Please help.
thanks
Well there are different ways that give different results
1 ) Wait until the work has finished. This is exactly what you've got with your code already. You'll start a thread and then wait for that thread to finish before continuing execution.
thread.Start();
thread.Join();
2) thread.ThreadState will tell you whether or not the thread has finished. In a basic scenario you could do the following. This would allow you to check the current thread state at any point in your code where you've got access to the state.
if(thread.ThreadState != ThreadState.Running){
// Thread has stopped
}
3) Using an event. A lot of Async examples will start some work and then trigger an event once the work has been completed. In this way you can sit watching for an event and respond once the work has completed. A usage example may look like the WebClient class
WebClient client = new WebClient();
client.DownloadFileCompleted += new
AsyncCompletedEventHandler(client_DownloadFileCompleted);
You can check for Thread.IsAlive property.
What you tried is a right way to wait for a thread to be done. But:
Thread.Join() is a function of Thread class.
Calling Join() function of a thread instance (in your sample testThreadd) will make the current thread to wait until testThreadd finishes it's job. Current thread is the thread which is calling testThreadd.Join()
In addition to the supplied answers, these days, the most used method would be by using Tasks. Besides having all the Wait and IsCompleted possibilities, these have the added advantage of having a ContinueWith method
start a task
var task = Task.Run((Action)TestMethod);
check completed
if (task.IsCompleted) { }
wait for task to finish (same as thread.sleep)
task.Wait();
setting a continuewith (additional task to be started after the task finishes)
var task = new Task((Action)TestMethod);
task.ContinueWith(t => MessageBox.Show("Finished"));
task.Start();
and combined, waiting for the continued task to finish (which automatically means, the first task is finished)
var task = new Task((Action)TestMethod);
var continuedtask = task.ContinueWith(t => MessageBox.Show("Finished"));
task.Start();
continuedtask.Wait();
You could use a BackgroundWorker instead of manually starting a new thread. It raises the RunWorkerCompleted event if its work is done (or if an exception occurs).
I have a function where I want to execute in a separate thread avoiding two threads to access the same resources. Also I want to make sure that if the thread is currently executing then stop that thread and start executing the new thread. This is what I have:
volatile int threadCount = 0; // use it to know the number of threads being executed
private void DoWork(string text, Action OncallbackDone)
{
threadCount++;
var t = new Thread(new ThreadStart(() =>
{
lock (_lock) // make sure that this code is only accessed by one thread
{
if (threadCount > 1) // if a new thread got in here return and let the last one execute
{
threadCount--;
return;
}
// do some work in here
Thread.Sleep(1000);
OncallbackDone();
threadCount--;
}
}));
t.Start();
}
if I fire that method 5 times then all the threads will be waiting for the lock until the lock is released. I want to make sure that I execute the last thread though. when the threads are waiting to be the owner of the lock how can I determine which will be the next one owning the lock. I want them to own the resource in the order that I created the threads...
EDIT
I am not creating this application with .net 4.0 . Sorry for not mentioning what I was trying to accomplish. I am creating an autocomplete control where I am filtering a lot of data. I don't want the main window to freeze eveytime I want to filter results. also I want to filter results as the user types. If the user types 5 letters at once I want to stop all threads and I will just be interested in the last one. because the lock blocks all the threads sometimes the last thread that I created may own the lock first.
I think you are overcomplicating this. If you are able to use 4.0, then just use the Task Parallel Library. With it, you can just set up a ContinueWith function so that threads that must happen in a certain order are done in the order you dictate. If this is NOT what you are looking for, then I actually would suggest that you not use threading, as this sounds like a synchronous action that you are trying to force into parallelism.
If you are just looking to cancel tasks: then here is a SO question on how to cancel TPL tasks. Why waste the resources if you are just going to dump them all except for the last one.
If you are not using 4.0, then you can accomplish the same thing with a Background Worker. It just takes more boilerplate code to accomplish the same thing :)
I agree with Justin in that you should use the .NET 4 Task Parallel Library. But if you want complete control you should not use the default Task Scheduler, which favors LIFO, but create your own Task Scheduler (http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx) and implement the logic that you want to determine which task gets preference.
Using Threads directly is not recommended unless you have deep knowledge of .NET Threading. If you are on .NET 4.0; Tasks and TPL are preferred.
This is what I came up with after reading the links that you guys posted. I guess I needed a Queue therefore I implemented:
volatile int threadCount = 0;
private void GetPredicateAsync(string text, Action<object> DoneCallback)
{
threadCount++;
ThreadPool.QueueUserWorkItem((x) =>
{
lock (_lock)
{
if (threadCount > 1) // disable executing threads at same time
{
threadCount--;
return; // if a new thread is created exit.
// let the newer task do work!
}
// do work in here
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
threadCount--;
DoneCallback(Foo);
}));
}
},text);
}
well, i make a loop that makes a lot of threads, see:
foreach (DataGridViewRow dgvRow in dataGridView1.Rows)
{
Class h = new Class(dgvRow.Cells["name"].Value.ToString());
Thread trdmyClass = new Thread(h.SeeInfoAboutName);
trdmyClass.IsBackground = true;
trdmyClass.Start();
}
This is working fine, creating the threads that i need, but i want to stop all this threads (using Thread.Abort()), in one time when i click on a button for e.g.
How can i do this?
I wouldn't use Thread.Abort. It can have some very nasty consequences. What you should be doing is keeping track of the threads you create by putting them into a list. You can then use a ManualResetEvent class. The threads should check if the reset was raised or not periodically and if it has been set, they should cleanup and exit. I use the WaitOne method will a millisecond timeout and then check the return value to allow threads to run in a loop. If true is returned the signal is set and you can exit the loop or otherwise return from your thread. If you're using .Net 4, you can also use a CancelationToken as well.
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx
http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.aspx
Read more about the issues with Thread.Abort here: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx
EDIT: I use a ManualResetEvent as its thread safe and you could use it to syncronize the processing in the threads, for example if you're doing a producer / consumer pattern. A volatile boolean could be used as well. I recommend keeping the threads in a list in case you need to wait for them to complete, so you can Join on each one. This may or may not be applicable to your problem though. Its usually a good idea, especially if you're exiting, to Join all your threads to allow them to finish any cleanup they may be doing.
You really shouldn't use Thread.Abort(), it can be very dangerous. Instead, you should provide some way to signal to the threads that they are canceled. Each thread would then periodically check whether it's canceled and end if it was.
One way to do this would be to use CancellationToken, which does exactly that. The framework methods that support cancellation work with this type too.
Your code could then look something like this:
// field to keep CancellationTokenSource:
CancellationTokenSource m_cts;
// in your method:
m_cts = new CancellationTokenSource();
foreach (DataGridViewRow dgvRow in dataGridView1.Rows)
{
Class h = new Class(dgvRow.Cells["name"].Value.ToString());
Thread trdmyClass = new Thread(() => h.SeeInfoAboutName(m_cts.Token));
trdmyClass.IsBackground = true;
trdmyClass.Start();
}
//somewhere else, where you want to cancel the threads:
m_cts.Cancel();
// the SeeInfoAboutName() method
public void SeeInfoAboutName(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
// do some work
}
}
Keep all the threads in a List, and then loop through the list and stop them.
I have a c# console application which has some threads to do some work (download a file).
each thread may exit the application at any time any where in application, but I'll show a proper message on console. It's possible to track them but it doesn't make sense to me. I want simply check thread count or something like that to find out which one is the last thread and do something when it is exiting.
What's the best practice to do so ?
pseudo code:
if (lastThread)
{
cleanUp();
Console.ReadLine();
}
Thanks
This is one place where using the new Task Parallel Library can make life much easier. Instead of creating threads, and spinning work up on the thread, you can use multiple tasks:
var task1 = Task.Factory.StartNew( () => DoTaskOneWork() );
var task2 = Task.Factory.StartNew( () => DoTaskTwoWork() );
var task3 = Task.Factory.StartNew( () => DoTaskThreeWork() );
// Block until all tasks are done
Task.WaitAll(new[] {task1, task2, task3} );
cleanUp(); // Do your cleanup
If the "tasks" are just downloading a bunch of individual files, you could even make this simpler using PLINQ:
var fileUrls = GetListOfUrlsToDownload();
fileUrls.AsParallel().ForAll( fileUrl => DownloadAndProcessFile(fileUrl) );
cleanUp(); // Do your cleanup
A design where you lose track of your threads is not ideal.
Depending on how you spawn them it ought to be possible to track the status of each by associating some per-thread signalable object, then WaitAll on those signalable objects.
Each signalable object in turn should get signaled as its thread exits. When they are all signaled, you know the threads are all dead and you close down clean. You have to make sure that abnormal conditions in your threads do not result in that thread's associated signalable object remaining unset, or your WaitAll will never return. This means exceptions typically - could use try...finally to ensure the objects get signaled.
Your new pseudocode is
foreach (workitem in list of work)
start up thread associated with a ManualResetEvent or similar
WaitAll for all events to be signalled
cleanup
Your main thread should join with all your worker threads and block while they are running. Then when all threads are complete it performs the cleanup code and then quits.
Alternatively you can use a WaitHandle such as as a ManualResetEvent per thread and wait for all of them to be signalled.
I have an application that uses 20 threads. It's an email client that uses threads to mail from.
Currently the threads are created in the main thread. But I am wondering, what if I want to cancel the whole operation? The only way I can see of doing it is killing the main thread ... thus ending the program.
Would I have to create a thread that encapsulates the threads for mailing so I can kill the encapsulating thread?
I am currently using BackgroundWorker by the way and it's a WF application.
If you are using a BackgroundWorker then you already have all of the infrastructure you need to cancel the operation. Simply set WorkerSupportsCancellation to true on the BackgroundWorker, and invoke the worker's CancelAsync method when you want to cancel.
Obviously you have to write the worker code to honour the cancellation. You do this by checking the CancellationPending property of the BackgroundWorker.
MSDN has an example of using this property.
Note - I am a bit confused by the combination of BackgroundWorker and 20 threads; a BackgroundWorker only uses one thread by itself. Are you spinning off 20 BackgroundWorkers? If so, how do you ensure that they're properly disposed? If you need that much concurrency in a Winforms app then it's better to use asynchronous delegates or the Thread Pool.
If you are creating actual threads, one common way of implementing a cancellation flag is to use a ManualResetEvent. If you wait on this event with zero timeout, it acts as a thread-safe status flag. An example usage would be:
ManualResetEvent cancelEvent = new ManualResetEvent(false);
for (int i = 0; i < 20; i++)
{
ThreadPool.QueueUserWorkItem(s =>
{
// Do some work
if (cancelEvent.WaitOne(0, true))
return;
// Do some more work
// etc.
});
}
Then at some point later if you write cancelEvent.Set(), every worker will stop its work as soon as it hits the status check.