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.
Related
I have a problem stopping a Parallel for each loop.
I am iterating over a set of about 40.000 DataRows retrieved from a table, and I need to stop my loop immediately when I have 100 items in my resultset. The problem is that when I trigger the Stop method on the ParallelLoopState, the iteration is not stopped immediately, causing inconsistency in my resultset ( either to few or to many items).
Is there no way to make sure, that I kill all threads, as soon as I hit stop?
List<DataRow> rows = new List<DataRow>(dataTable.Select());
ConcurrentDictionary<string, object> resultSet = new ConcurrentDictionary<string, object>();
rows.EachParallel(delegate (DataRow row, ParallelLoopState state)
{
if (!state.IsStopped)
{
using (SqlConnection sqlConnection = new SqlConnection(Global.ConnStr))
{
sqlConnection.Open();
//{
// Do some processing.......
//}
var sourceKey = "key retrieved from processing";
if (!resultSet.ContainsKey(sourceKey))
{
object myCustomObj = new object();
resultSet.AddOrUpdate(
sourceKey,
myCustomObj,
(key, oldValue) => myCustomObj);
}
if (resultSet.Values.Count == 100)
state.Stop();
}
}
});
The documentation page of ParallelLoopState.Stop explains that calling Stop() will prevent new iterations from starting. It won't abort any existing iterations.
Stop() also sets the IsStopped property to true. Long running iterations can check the value of IsStopped and exit prematurely if required.
This is called cooperative cancellation which is far better than aborting threads. Aborting a thread is expensive and makes cleanup difficult. Imagine what would happen if a ThreadAbort exception was thrown just when you wanted to commit your work.
Cooperative cancellation on the other hand allows a task to exit gracefully after commiting or aborting transactions as necessary, closing connections, cleaning up other state and files etc.
Furthermore, Parallel uses tasks, not threads, to process chunks of data. One of those threads is the original thread that started the parallel operation. Aborting wouldn't just waste threadpool threads, it would also kill the main thread.
This is not a bug either - Parallel is meant to solve data parallelism problems, not asynchronous execution. In this scenario, one wants the system to use as many tasks as appropriate to process the data and continue once that processing is complete.
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.
I just wanted to ask a clarification about the program below:
foreach (Match match in MC)
{
string link = match.Groups["link"].ToString();
if (link.Contains("ebay.de/itm/"))
{
int endIndex = link.IndexOf("?pt");
link = link.Substring(0, endIndex);
if (link != lastLink)
{
getEanPerLink = delegate
{
getEan(link);
};
new Thread(getEanPerLink).Start();
}
lastLink = link;
}
}
It creates a lot of threads when the program loops. I just wanted to ask if those threads ends or exits itself. Or if not, how can I abort each of those threads created?
Each thread will end when the getEan method exits. If it does, then you don't have to do anything more, the thread and the Thread object will go away cleanly.
It's possible to abort threads, but it's not recommended because it throws an exception in the middle of whatever the thread is doing. The recommended way is to communicate to the thread that you want it to end, so that it can do that at a convenient place in the code.
Make them as background threads than thay will be closed when you close or abort the running thread.
My recommnedition do not use threads in this; way this is a bad way to use thread.
if you r using .net 4.5 use async await
if you r using .net 4 use Task
if you r using .net 3.5 use ThreadPool
if you r using .net 2 backgroundWorker
Greertings,
Bassam
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);
}
I have a class that implements the Begin/End Invocation pattern where I initially used ThreadPool.QueueUserWorkItem() to thread my work. The work done on the thread doesn't loop but does takes a bit of time to process so the work itself is not easily stopped.
I now have the side effect where someone using my class is calling the Begin (with callback) a ton of times to do a lot of processing so ThreadPool.QueueUserWorkItem is creating a ton of threads to do the processing. That in itself isn't bad but there are instances where they want to abandon the processing and start a new process but they are forced to wait for their first request to finish.
Since ThreadPool.QueueUseWorkItem() doesn't allow me to cancel the threads I am trying to come up with a better way to queue up the work and maybe use an explicit FlushQueue() method in my class to allow the caller to abandon work in my queue.
Anyone have any suggestion on a threading pattern that fits my needs?
Edit: I'm currently targeting the 2.0 framework. I'm currently thinking that a Consumer/Producer queue might work. Does anyone have thoughts on the idea of flushing the queue?
Edit 2 Problem Clarification:
Since I'm using the Begin/End pattern in my class every time the caller uses the Begin with callback I create a whole new thread on the thread pool. This call does a very small amount of processing and is not where I want to cancel. It's the uncompleted jobs in the queue I wish to stop.
The fact that the ThreadPool will create 250 threads per processor by default means if you ask the ThreadPool to queue a large amount of items with QueueUserWorkItem() you end up creating a huge amount of concurrent threads that you have no way of stopping.
The caller is able to push the CPU to 100% with not only the work but the creation of the work because of the way I queued the threads.
I was thinking by using the Producer/Consumer pattern I could queue these threads into my own queue that would allow me to moderate how many threads I create to avoid the CPU spike creating all the concurrent threads. And that I might be able to allow the caller of my class to flush all the jobs in the queue when they are abandoning the requests.
I am currently trying to implement this myself but figured SO was a good place to have someone say look at this code or you won't be able to flush because of this or flushing isn't the right term you mean this.
EDIT My answer does not apply since OP is using 2.0. Leaving up and switching to CW for anyone who reads this question and using 4.0
If you are using C# 4.0, or can take a depedency on one of the earlier version of the parallel frameworks, you can use their built-in cancellation support. It's not as easy as cancelling a thread but the framework is much more reliable (cancelling a thread is very attractive but also very dangerous).
Reed did an excellent article on this you should take a look at
http://reedcopsey.com/2010/02/17/parallelism-in-net-part-10-cancellation-in-plinq-and-the-parallel-class/
A method I've used in the past, though it's certainly not a best practice is to dedicate a class instance to each thread, and have an abort flag on the class. Then create a ThrowIfAborting method on the class that is called periodically from the thread (particularly if the thread's running a loop, just call it every iteration). If the flag has been set, ThrowIfAborting will simply throw an exception, which is caught in the main method for the thread. Just make sure to clean up your resources as you're aborting.
You could extend the Begin/End pattern to become the Begin/Cancel/End pattern. The Cancel method could set a cancel flag that the worker thread polls periodically. When the worker thread detects a cancel request, it can stop its work, clean-up resources as needed, and report that the operation was canceled as part of the End arguments.
I've solved what I believe to be your exact problem by using a wrapper class around 1+ BackgroundWorker instances.
Unfortunately, I'm not able to post my entire class, but here's the basic concept along with it's limitations.
Usage:
You simply create an instance and call RunOrReplace(...) when you want to cancel your old worker and start a new one. If the old worker was busy, it is asked to cancel and then another worker is used to immediately execute your request.
public class BackgroundWorkerReplaceable : IDisposable
{
BackgroupWorker activeWorker = null;
object activeWorkerSyncRoot = new object();
List<BackgroupWorker> workerPool = new List<BackgroupWorker>();
DoWorkEventHandler doWork;
RunWorkerCompletedEventHandler runWorkerCompleted;
public bool IsBusy
{
get { return activeWorker != null ? activeWorker.IsBusy; : false }
}
public BackgroundWorkerReplaceable(DoWorkEventHandler doWork, RunWorkerCompletedEventHandler runWorkerCompleted)
{
this.doWork = doWork;
this.runWorkerCompleted = runWorkerCompleted;
ResetActiveWorker();
}
public void RunOrReplace(Object param, ...) // Overloads could include ProgressChangedEventHandler and other stuff
{
try
{
lock(activeWorkerSyncRoot)
{
if(activeWorker.IsBusy)
{
ResetActiveWorker();
}
// This works because if IsBusy was false above, there is no way for it to become true without another thread obtaining a lock
if(!activeWorker.IsBusy)
{
// Optionally handle ProgressChangedEventHandler and other features (under the lock!)
// Work on this new param
activeWorker.RunWorkerAsync(param);
}
else
{ // This should never happen since we create new workers when there's none available!
throw new LogicException(...); // assert or similar
}
}
}
catch(...) // InvalidOperationException and Exception
{ // In my experience, it's safe to just show the user an error and ignore these, but that's going to depend on what you use this for and where you want the exception handling to be
}
}
public void Cancel()
{
ResetActiveWorker();
}
public void Dispose()
{ // You should implement a proper Dispose/Finalizer pattern
if(activeWorker != null)
{
activeWorker.CancelAsync();
}
foreach(BackgroundWorker worker in workerPool)
{
worker.CancelAsync();
worker.Dispose();
// perhaps use a for loop instead so you can set worker to null? This might help the GC, but it's probably not needed
}
}
void ResetActiveWorker()
{
lock(activeWorkerSyncRoot)
{
if(activeWorker == null)
{
activeWorker = GetAvailableWorker();
}
else if(activeWorker.IsBusy)
{ // Current worker is busy - issue a cancel and set another active worker
activeWorker.CancelAsync(); // Make sure WorkerSupportsCancellation must be set to true [Link9372]
// Optionally handle ProgressEventHandler -=
activeWorker = GetAvailableWorker(); // Ensure that the activeWorker is available
}
//else - do nothing, activeWorker is already ready for work!
}
}
BackgroupdWorker GetAvailableWorker()
{
// Loop through workerPool and return a worker if IsBusy is false
// if the loop exits without returning...
if(activeWorker != null)
{
workerPool.Add(activeWorker); // Save the old worker for possible future use
}
return GenerateNewWorker();
}
BackgroundWorker GenerateNewWorker()
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true; // [Link9372]
//worker.WorkerReportsProgress
worker.DoWork += doWork;
worker.RunWorkerCompleted += runWorkerCompleted;
// Other stuff
return worker;
}
} // class
Pro/Con:
This has the benefit of having a very low delay in starting your new execution, since new threads don't have to wait for old ones to finish.
This comes at the cost of a theoretical never-ending growth of BackgroundWorker objects that never get GC'd. However, in practice the code below attempts to recycle old workers so you shouldn't normally encounter a large pool of ideal threads. If you are worried about this because of how you plan to use this class, you could implement a Timer which fires a CleanUpExcessWorkers(...) method, or have ResetActiveWorker() do this cleanup (at the cost of a longer RunOrReplace(...) delay).
The main cost from using this is precisely why it's beneficial - it doesn't wait for the previous thread to exit, so for example, if DoWork is performing a database call and you execute RunOrReplace(...) 10 times in rapid succession, the database call might not be immediately canceled when the thread is - so you'll have 10 queries running, making all of them slow! This generally tends to work fine with Oracle, causing only minor delays, but I do not have experiences with other databases (to speed up the cleanup, I have the canceled worker tell Oracle to cancel the command). Proper use of the EventArgs described below mostly solves this.
Another minor cost is that whatever code this BackgroundWorker is performing must be compatible with this concept - it must be able to safely recover from being canceled. The DoWorkEventArgs and RunWorkerCompletedEventArgs have a Cancel/Cancelled property which you should use. For example, if you do Database calls in the DoWork method (mainly what I use this class for), you need to make sure you periodically check these properties and take perform the appropriate clean-up.