I've been working on a web crawling .NET app in my free time, and one of the features of this app that I wanted to included was a pause button to pause a specific thread.
I'm relatively new to multi-threading and I haven't been able to figure out a way to pause a thread indefinitely that is currently supported. I can't remember the exact class/method, but I know there is a way to do this but it has been flagged as obsolete by the .NET framework.
Is there any good general purpose way to indefinitely pause a worker thread in C# .NET.
I haven't had a lot of time lately to work on this app and the last time I touched it was in the .NET 2.0 framework. I'm open to any new features (if any) that exist in the .NET 3.5 framework, but I'd like to know of solution that also works in the 2.0 framework since that's what I use at work and it would be good to know just in case.
Never, ever use Thread.Suspend. The major problem with it is that 99% of the time you can't know what that thread is doing when you suspend it. If that thread holds a lock, you make it easier to get into a deadlock situation, etc. Keep in mind that code you are calling may be acquiring/releasing locks behind the scenes. Win32 has a similar API: SuspendThread and ResumeThread. The following docs for SuspendThread give a nice summary of the dangers of the API:
http://msdn.microsoft.com/en-us/library/ms686345(VS.85).aspx
This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.
The proper way to suspend a thread indefinitely is to use a ManualResetEvent. The thread is most likely looping, performing some work. The easiest way to suspend the thread is to have the thread "check" the event each iteration, like so:
while (true)
{
_suspendEvent.WaitOne(Timeout.Infinite);
// Do some work...
}
You specify an infinite timeout so when the event is not signaled, the thread will block indefinitely, until the event is signaled at which point the thread will resume where it left off.
You would create the event like so:
ManualResetEvent _suspendEvent = new ManualResetEvent(true);
The true parameter tells the event to start out in the signaled state.
When you want to pause the thread, you do the following:
_suspendEvent.Reset();
And to resume the thread:
_suspendEvent.Set();
You can use a similar mechanism to signal the thread to exit and wait on both events, detecting which event was signaled.
Just for fun I'll provide a complete example:
public class Worker
{
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
ManualResetEvent _pauseEvent = new ManualResetEvent(true);
Thread _thread;
public Worker() { }
public void Start()
{
_thread = new Thread(DoWork);
_thread.Start();
}
public void Pause()
{
_pauseEvent.Reset();
}
public void Resume()
{
_pauseEvent.Set();
}
public void Stop()
{
// Signal the shutdown event
_shutdownEvent.Set();
// Make sure to resume any paused threads
_pauseEvent.Set();
// Wait for the thread to exit
_thread.Join();
}
public void DoWork()
{
while (true)
{
_pauseEvent.WaitOne(Timeout.Infinite);
if (_shutdownEvent.WaitOne(0))
break;
// Do the work here..
}
}
}
The Threading in C# ebook summarises Thread.Suspend and Thread.Resume thusly:
The deprecated Suspend and Resume methods have two modes – dangerous and useless!
The book recommends using a synchronization construct such as an AutoResetEvent or Monitor.Wait to perform thread suspending and resuming.
If there are no synchronization requirements:
Thread.Sleep(Timeout.Infinite);
I just implemented a LoopingThread class which loops an action passed to the constructor. It is based on Brannon's post. I've put some other stuff into that like WaitForPause(), WaitForStop(), and a TimeBetween property, that indicates the time that should be waited before next looping.
I also decided to change the while-loop to an do-while-loop. This will give us a deterministic behavior for a successive Start() and Pause(). With deterministic I mean, that the action is executed at least once after a Start() command. In Brannon's implementation this might not be the case.
I omitted some things for the root of the matter. Things like "check if the thread was already started", or the IDisposable pattern.
public class LoopingThread
{
private readonly Action _loopedAction;
private readonly AutoResetEvent _pauseEvent;
private readonly AutoResetEvent _resumeEvent;
private readonly AutoResetEvent _stopEvent;
private readonly AutoResetEvent _waitEvent;
private readonly Thread _thread;
public LoopingThread (Action loopedAction)
{
_loopedAction = loopedAction;
_thread = new Thread (Loop);
_pauseEvent = new AutoResetEvent (false);
_resumeEvent = new AutoResetEvent (false);
_stopEvent = new AutoResetEvent (false);
_waitEvent = new AutoResetEvent (false);
}
public void Start ()
{
_thread.Start();
}
public void Pause (int timeout = 0)
{
_pauseEvent.Set();
_waitEvent.WaitOne (timeout);
}
public void Resume ()
{
_resumeEvent.Set ();
}
public void Stop (int timeout = 0)
{
_stopEvent.Set();
_resumeEvent.Set();
_thread.Join (timeout);
}
public void WaitForPause ()
{
Pause (Timeout.Infinite);
}
public void WaitForStop ()
{
Stop (Timeout.Infinite);
}
public int PauseBetween { get; set; }
private void Loop ()
{
do
{
_loopedAction ();
if (_pauseEvent.WaitOne (PauseBetween))
{
_waitEvent.Set ();
_resumeEvent.WaitOne (Timeout.Infinite);
}
} while (!_stopEvent.WaitOne (0));
}
}
Beside suggestions above, I'd like to add one tip. In some cases, use BackgroundWorker can simplify your code (especially when you use anonymous method to define DoWork and other events of it).
In line with what the others said - don't do it. What you really want to do is to "pause work", and let your threads roam free. Can you give us some more details about the thread(s) you want to suspend? If you didn't start the thread, you definitely shouldn't even consider suspending it - its not yours. If it is your thread, then I suggest instead of suspending it, you just have it sit, waiting for more work to do. Brannon has some excellent suggestions for this option in his response. Alternatively, just let it end; and spin up a new one when you need it.
The Suspend() and Resume() may be depricated, however they are in no way useless.
If, for example, you have a thread doing a lengthy work altering data, and the user wishes to stop it, he clicks on a button. Of course, you need to ask for verification, but, at the same time you do not want that thread to continue altering data, if the user decides that he really wants to abort.
Suspending the Thread while waiting for the user to click that Yes or No button at the confirmation dialog is the only way to prevent it from altering the data, before you signal the designated abort event that will allow it to stop.
Events may be nice for simple threads having one loop, but complicated threads with complex processing is another issue.
Certainly, Suspend() must never be used for syncronising, since its usefulness is not for this function.
Just my opinion.
Related
I'm playing around with a simple console app that creates one thread and I do some inter thread communication between the main and the worker thread.
I'm posting objects from the main thread to a concurrent queue and the worker thread is dequeueing that and does some processing.
What strikes me as odd, is that when I profile this app, even despite I have two cores.
One core is 100% free and the other core have done all the work, and I see that both threads have been running in that core.
Why is this?
Is it because I use a wait handle that sets when I post a message and releases when the processing is done?
This is my sample code, now using 2 worker threads.
It still behaves the same, main, worker1 and worker2 is running in the same core.
Ideas?
[EDIT]
It sort of works now, atleast, I get twice the performance compared to yesterday.
the trick was to slow down the consumer just enough to avoid signaling using the AutoResetEvent.
public class SingleThreadDispatcher
{
public long Count;
private readonly ConcurrentQueue<Action> _queue = new ConcurrentQueue<Action>();
private volatile bool _hasMoreTasks;
private volatile bool _running = true;
private int _status;
private readonly AutoResetEvent _signal = new AutoResetEvent(false);
public SingleThreadDispatcher()
{
var thread = new Thread(Run)
{
IsBackground = true,
Name = "worker" + Guid.NewGuid(),
};
thread.Start();
}
private void Run()
{
while (_running)
{
_signal.WaitOne();
do
{
_hasMoreTasks = false;
Action task;
while (_queue.TryDequeue(out task) && _running)
{
Count ++;
task();
}
//wait a short while to let _hasMoreTasks to maybe be set to true
//this avoids the roundtrip to the AutoResetEvent
//that is, if there is intense pressure on the pool, we let some new
//tasks have the chance to arrive and be processed w/o signaling
if(!_hasMoreTasks)
Thread.Sleep(5);
Interlocked.Exchange(ref _status, 0);
} while (_hasMoreTasks);
}
}
public void Schedule(Action task)
{
_hasMoreTasks = true;
_queue.Enqueue(task);
SetSignal();
}
private void SetSignal()
{
if (Interlocked.Exchange(ref _status, 1) == 0)
{
_signal.Set();
}
}
}
Is it because I use a wait handle that sets when I post a message and releases when the processing is done?
Without seeing your code it is hard to say for sure, but from your description it appears that the two threads that you wrote act as co-routines: when the main thread is running, the worker thread has nothing to do, and vice versa. It looks like .NET scheduler is smart enough to not load the second core when this happens.
You can change this behavior in several ways - for example
by doing some work on the main thread before waiting on the handle, or
by adding more worker threads that would compete for the tasks that your main thread posts, and could both get a task to work on.
OK, I've figured out what the problem is.
The producer and consumer is pretty much just as fast in this case.
This results in the consumer finishing all its work fast and then looping back to wait for the AutoResetEvent.
The next time the producer sends a task, it has to touch the AutoresetEvent and set it.
The solution was to add a very very small delay in the consumer, making it slightly slower than the producer.
This results in when the producer sends a task, it notices that the consumer is already active and it just has to post to the worker queue w/o touching the AutoResetEvent.
The original behavior resulted in a sort of ping-pong effect, that can be seen on the screenshot.
Dasblinkelight (probably) has the right answer.
Apart from that, it would also be the correct behaviour when one of your threads is I/O bound (that is, it's not stuck on the CPU) - in that case, you've got nothing to gain from using multiple cores, and .NET is smart enough to just change contexts on one core.
This is often the case for UI threads - it has very little work to do, so there usually isn't much of a reason for it to occupy a whole core for itself. And yes, if your concurrent queue is not used properly, it could simply mean that the main thread waits for the worker thread - again, in that case, there's no need to switch cores, since the original thread is waiting anyway.
You should use BlockingCollection rather than ConcurrentQueue. By default, BlockingCollection uses a ConcurrentQueue under the hood, but it has a much easier to use interface. In particular, it does non-busy waits. In addition, BlockingCollection supports cancellation, so your consumer becomes very simple. Here's an example:
public class SingleThreadDispatcher
{
public long Count;
private readonly BlockingCollection<Action> _queue = new BlockingCollection<Action>();
private readonly CancellationTokenSource _cancellation = new CancellationTokenSource();
public SingleThreadDispatcher()
{
var thread = new Thread(Run)
{
IsBackground = true,
Name = "worker" + Guid.NewGuid(),
};
thread.Start();
}
private void Run()
{
foreach (var task in _queue.GetConsumingEnumerable(_cancellation.Token))
{
Count++;
task();
}
}
public void Schedule(Action task)
{
_queue.Add(task);
}
}
The loop with GetConsumingEnumerable will do a non-busy wait on the queue. There's no need to do it with a separate event. It will wait for an item to be added to the queue, or it will exit if you set the cancellation token.
To stop it normally, you just call _queue.CompleteAdding(). That tells the consumer that no more items will be added to the queue. The consumer will empty the queue and then exit.
If you want to quit early, then just call _cancellation.Cancel(). That will cause GetConsumingEnumerable to exit.
In general, you shouldn't ever have to use ConcurrentQueue directly. BlockingCollection is easier to use and provides equivalent performance.
I've found this topic, How to suspend a thread by its name from the main thread?, but no satisfactory answer for what I'm trying to achieve.
I'm using threading and the WatiN class to perform events on two browsers in the same windows form at the same time.
I would like to, from the main UI thread, press a pause button available within one of the browsers that, through deriving the control name of the browser the pause button was pressed on, use that' name to figure out which sub-thread is associated with it's running logic, and pause that running logic until the play button is pressed.
Now today, we are so accomplished in terms of code and technology, there should be a way to do this.
What do you think?
Researching Ideas:
Pragmatically create ManualResetEvent and name it, use the UI pause button to grab the open browser control name, which is similiarly named after the child thread and browser control name (such a browser_5 & thread_5) to somehow target in on the MRE in the child thread, and close the gate to pause the logic. (But can this be done on child thread from the main UI thread?)
Don't use thread.Suspend
At first blush, it seems you could use thread.Suspend() to pause it and thread.Resume() to unpause it. But this is not a very good idea. See the MSDN article for thread.Suspend for why you should never use it unless you intend to terminate the AppDomain for that thread.
Do not use the Suspend and Resume methods to synchronize the activities of threads. You have no way of knowing what code a thread is executing when you suspend it. If you suspend a thread while it holds locks during a security permission evaluation, other threads in the AppDomain might be blocked. If you suspend a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use that class are blocked. Deadlocks can occur very easily.
A sub-loop would work, but isn't perfect
It isn't the best option, but you could use a similar technique to the one described in that question you linked.
Instead of exiting the loop when a stop button is pressed, have it enter and wait inside a sub-loop while paused. Do a Thread.Sleep in that sub-loop to keep the CPU from pegging.
This isn't the most efficient code possible, because it keeps the thread running, and hangs for another 100ms when resuming.
public class YourForm : Form
{
private volatile bool _pause = false;
private void StartButton_Click(object sender, EventArgs e)
{
var thread = new Thread(
() =>
{
while (...)
{
// Periodically poll the _pause flag.
while (_pause)
{
// Now that we're paused, wait until we're unpaused
// before proceeding further in the outer loop
Thread.Sleep(100);
}
// Todo: The rest of the processing here
}
});
thread.Start();
}
private void PauseButton_Click(object sender, EventArgs e)
{
_pause = !_pause; // Toggle
}
}
Use thread synchronization
The best option is to use one of the various thread synchronization structures, like ManualResetEvent. Pausing threads is exactly what they're designed for. They're very efficient because they are implemented with a mutex.
public class YourForm : Form
{
private volatile bool _pause = false;
private static ManualResetEvent mre = new ManualResetEvent(true);
private void StartButton_Click(object sender, EventArgs e)
{
var thread = new Thread(ThreadImplementation);
thread.Start();
}
private void PauseButton_Click(object sender, EventArgs e)
{
_pause = !_pause;
if(_pause)
{
mre.Reset();
}
else
{
mre.Set();
}
}
private void ThreadImplementation()
{
while (...)
{
// Periodically wait on the event
mre.WaitOne();
// Todo: The rest of the processing here
}
}
}
Your ManualResetEvent idea is exactly correct.
Make the child threads WaitOne() on the event between each step.
To pause the request, call Reset(); to unpause, call Set().
If the event is set, WaitOne() will return immediately.
This will be much more efficient than repeated sleeps.
I suspect that a ManualResetEventSlim would be slightly faster.
I am writing a GUI application.
The application is opening multiple threads during it's life time. One of the threads is handling events that can come from other applications, so it is waiting in a while(true) loop for the event which is never been terminated.
The user can close the application in any minute. I want to close all the threads that the main application had opened.
I am using Process.GetCurrentProcess().Kill(); to deal with this problem at the moment.
Is this a good solution? If not, why and what is the proper way to deal with this problem, how to close all threads that were opened by the main application?
If you create the new threads as background threads (by setting IsBackground before starting them), they will automatically stop when the main thread (the application thread) terminates.
(From MSDN):
A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.
Once you already have threads waiting for some events, just add one more event that when triggered will instruct the thread to terminate.
In case you don't need to provide some means of graceful shutdown for other threads, you can switch them into the “background thread” mode to ensure automatic termination — see MSDN for a thorough discussion of this topic.
There are a lot of ways to deal with this, but ideally you want your threads to exit normally on their own rather than just killing the process.
You could do something very simple like this:
public class ThreadSignal
{
public bool Stop { get; set; }
}
Then in your thread loop, do:
public void DoWork(object state)
{
ThreadSignal signal = (ThreadSignal)state;
while(!signal.Stop)
{
// Do work here
}
}
Then when you're ready to stop, set your ThreadSignal.Stop to true. This is a very simple example, but it gives you a starting point.
You should wait in the loop with a ManualResetEvent (or AutoResetEvent).
Then just set a member variable to true when you are shutting down:
public class MyForm : Form
{
private AutoResetEvent _workTrigger = new AutoResetEvent();
private bool _shuttingDown = false;
private Thread _thread;
public void Form_Initialize()
{
_thread = new Thread(MyThreadMethod);
_thread.Start();
}
public static void MyThreadMethod(object State)
{
while (!_shuttingDown)
{
//wait for jobs.
_workTrigger.WaitOne(); //can add a timeout as parameter.
//do some work here
}
}
public void Form_Closing(object source, EventArgs e)
{
_shuttingDown = true;
_workTrigger.Set();
//wait for it to exit. You could use the timeout
//parameter and a loop to not block the UI
_thread.Join();
}
}
As you mentioned it's a GUI application so the main thread which is responsible for message loop is responsible for alerting the infinite (while(true)) loop that user wants to exit the program. I recommend to replace true with another boolean for signaling that user has closed the window like this: while(windowIsOpen) and set it to false on the unload of your form.
Don't lose your threads around the application - keep'em somewhere (List<Thread> will do fine). Then when the time is right (closing time) notify each one that it should finish what it's doing and exit.
Then, .Join() all of them, then allow application to exit.
Don't ever go to 'ThreadAbort' realm, it's dark side of the force that lurks there.
Generally how I do this is:
Create a Class that encapsulates this behavior (e.g. handling incoming messages in the background
Have the Class inherit from IDisposable. When Dispose() is called set a private variable named _disposed
Create my dedicated thread in my Class constructor.
Have a private AutoResetEvent named _workToDo. Your background thread will wait on this event and only do a work loop when this event is signaled.
Have a public method to send the message to your background worker that queues the work up and then sets _workToDo to tell your background thread to do the work.
Putting this all together, you get:
public class BackgroundProcessor : IDisposed
{
private Thread _backgroundThread;
private bool _disposed;
private AutoResetEvent _workToDo = new AutoResetEvent(false);
// where T is a class with the set of parameters for your background work
private Queue<T> _workQueue = Queue.Synchronized(new Queue<T>);
public BackgroundProcessor()
{
_backgroundThread = new Thread(DoBackgroundWork);
_backgroundThread.Start();
}
public void Dispose()
{
_disposed = true;
// Wait 5 seconds for the processing of any previously submitted work to finish.
// This gives you a clean exit. May want to check return value for timeout and log
// a warning if pending background work was not completed in time.
// If you're not sure what you want to do yet, a Debug.Assert is a great place to
// start because it will let you know if you do or don't go over time in general
// in your debug builds.
// Do *not* Join() and wait infinitely. This is a great way to introduce shutdown
// hangs into your app where your UI disappears but your process hangs around
// invisibly forever. Nasty problem to debug later...
Debug.Assert(_backgroundThread.Join(5000));
}
// Called by your 'other application'
public void GiveMeWorkToDo(T workParameters)
{
_workQueue.Enqueue(workParameters);
_workToDo.Set();
}
private void DoBackgroundWork()
{
while (!_disposed)
{
// 500 ms timeout to WaitOne allows your Dispose event to be detected if there is
// No work being submitted. This is a fancier version of a Thread.Sleep(500)
// loop. This is better because you will immediately start work when a new
// message is posted instead of waiting for the current Sleep statement to time
// out first.
_workToDo.WaitOne(500);
// It's possible multiple sets of work accumulated or that the previous loop picked up the work and there's none left. This is a thread safe way of handling this.
T workParamters = _workQueue.Count > 0 ? workParameters = _workQueue.Dequeue() : null;
do
{
DoSomething(workParameters);
workParameters = _workQueue.Count > 0 ? workParameters = _workQueue.Dequeue() : null;
} while (workParameters != null)
}
}
}
Consider using the BackGroundWorker class. Since it's using the threadpool (via BeginInvoke()), you'd get background threads. As a bonus you get convenient progress reporting, cancellation and completion callbacks (already marshalled to the UI thread).
I would like to start x number of threads from my .NET application, and I would like to keep track of them as I will need to terminate them manually or when my application closes my application later on.
Example ==> Start Thread Alpha, Start Thread Beta .. then at any point in my application I should be able to say Terminate Thread Beta ..
What is the best way to keep track of opened threads in .NET and what do I need to know ( an id ? ) about a thread to terminate it ?
You could save yourself the donkey work and use this Smart Thread Pool. It provides a unit of work system which allows you to query each thread's status at any point, and terminate them.
If that is too much bother, then as mentioned anIDictionary<string,Thread> is probably the simplest solution. Or even simpler is give each of your thread a name, and use an IList<Thread>:
public class MyThreadPool
{
private IList<Thread> _threads;
private readonly int MAX_THREADS = 25;
public MyThreadPool()
{
_threads = new List<Thread>();
}
public void LaunchThreads()
{
for (int i = 0; i < MAX_THREADS;i++)
{
Thread thread = new Thread(ThreadEntry);
thread.IsBackground = true;
thread.Name = string.Format("MyThread{0}",i);
_threads.Add(thread);
thread.Start();
}
}
public void KillThread(int index)
{
string id = string.Format("MyThread{0}",index);
foreach (Thread thread in _threads)
{
if (thread.Name == id)
thread.Abort();
}
}
void ThreadEntry()
{
}
}
You can of course get a lot more involved and complicated with it. If killing your threads isn't time sensitive (for example if you don't need to kill a thread in 3 seconds in a UI) then a Thread.Join() is a better practice.
And if you haven't already read it, then Jon Skeet has this good discussion and solution for the "don't use abort" advice that is common on SO.
You can create a Dictionary of threads and assign them id's, like:
Dictionary<string, Thread> threads = new Dictionary<string, Thread>();
for(int i = 0 ;i < numOfThreads;i++)
{
Thread thread = new Thread(new ThreadStart(MethodToExe));
thread.Name = threadName; //Any name you want to assign
thread.Start(); //If you wish to start them straight away and call MethodToExe
threads.Add(id, thread);
}
If you don't want to save threads against an Id you can use a list and later on just enumerate it to kill threads.
And when you wish to terminate them, you can abort them. Better have some condition in your MethodToExe that allows that method to leave allowing the thread to terminate gracefully. Something like:
void MethodToExe()
{
while(_isRunning)
{
//you code here//
if(!_isRunning)
{
break;
}
//you code here//
}
}
To abort you can enumerate the dictionary and call Thread.Abort(). Be ready to catch ThreadAbortException
I asked a similar questions and received a bunch of good answers: Shutting down a multithreaded application
Note: my question did not require a graceful exit, but people still recommended that I gracefully exit from the loop of each thread.
The main thing to remember is that if you want to avoid having your threads prevent your process from terminating you should set all your threads to background:
Thread thread = new Thread(new ThreadStart(testObject.RunLoop));
thread.IsBackground = true;
thread.start();
The preferred way to start and manage threads is in a ThreadPool, but just about any container out there can be used to keep a reference to your threads. Your threads should always have a flag that will tell them to terminate and they should continually check it.
Furthermore, for better control you can supply your threads with a CountdownLatch: whenever a thread is exiting its loop it will signal on a CountdownLatch. Your main thread will call the CountdownLatch.Wait() method and it will block until all the threads have signaled... this allows you to properly cleanup and ensures that all your threads have shutdown before you start cleaning up.
public class CountdownLatch
{
private int m_remain;
private EventWaitHandle m_event;
public CountdownLatch(int count)
{
Reset(count);
}
public void Reset(int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException();
m_remain = count;
m_event = new ManualResetEvent(false);
if (m_remain == 0)
{
m_event.Set();
}
}
public void Signal()
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref m_remain) == 0)
m_event.Set();
}
public void Wait()
{
m_event.WaitOne();
}
}
It's also worthy to mention that the Thread.Abort() method does some strange things:
When a thread calls Abort on itself,
the effect is similar to throwing an
exception; the ThreadAbortException
happens immediately, and the result is
predictable. However, if one thread
calls Abort on another thread, the
abort interrupts whatever code is
running. There is also a chance that a
static constructor could be aborted.
In rare cases, this might prevent
instances of that class from being
created in that application domain. In
the .NET Framework versions 1.0 and
1.1, there is a chance the thread could abort while a finally block is
running, in which case the finally
block is aborted.
The thread that calls Abort might
block if the thread that is being
aborted is in a protected region of
code, such as a catch block, finally
block, or constrained execution
region. If the thread that calls Abort
holds a lock that the aborted thread
requires, a deadlock can occur.
After creating your thread, you can set it's Name property. Assuming you store it in some collection you can access it conveniently via LINQ in order to retrieve (and abort) it:
var myThread = (select thread from threads where thread.Name equals "myThread").FirstOrDefault();
if(myThread != null)
myThread.Abort();
Wow, there are so many answers..
You can simply use an array to hold the threads, this will only work if the access to the array will be sequantial, but if you'll have another thread accessing this array, you will need to synchronize access
You can use the thread pool, but the thread pool is very limited and can only hold fixed amount of threads.
As mentioned above, you can create you own thread pool, which in .NET v4 becomes much easier with the introduction of safe collections.
you can manage them by holding a list of mutex object which will determine when those threads should finish, the threads will query the mutex each time they run before doing anything else, and if its set, terminate, you can manage the mutes from anywhere, and since mutex are by defenition thread-safe, its fairly easy..
i can think of another 10 ways, but those seems to work. let me know if they dont fit your needs.
Depends on how sophisticated you need it to be. You could implement your own type of ThreadPool with helper methods etc. However, I think its as simple as just maintaining a list/array and adding/removing the threads to/from the collection accordingly.
You could also use a Dictionary collection and use your own type of particular key to retrieve them i.e. Guids/strings.
As you start each thread, put it's ManagedThreadId into a Dictionary as the key and the thread instance as the value. Use a callback from each thread to return its ManagedThreadId, which you can use to remove the thread from the Dictionary when it terminates. You can also walk the Dictionary to abort threads if needed. Make the threads background threads so that they terminate if your app terminates unexpectedly.
You can use a separate callback to signal threads to continue or halt, which reflects a flag set by your UI, for a graceful exit. You should also trap the ThreadAbortException in your threads so that you can do any cleanup if you have to abort threads instead.
I encountered a strange problem with our Windows C# / .NET application. Actually it is a GUI application, my job is the included network component, encapsulated in an assembly. I do not know the code of the main/GUI application, I could contact it's developer though.
Now the application's UI has buttons to "Start" and "Stop" the network engine. Both buttons work.
To make my component threadsafe I am using a lock around three methods. I dont't want a client to be able to call Stop() before Start() finished. Additinally there is a Polling Timer.
I tried to show you as few lines as possible and simpified the problem:
private Timer actionTimer = new Timer(new
TimerCallback(actionTimer_TimerCallback),
null, Timeout.Infinite, Timeout.Infinite);
public void Start()
{
lock (driverLock)
{
active = true;
// Trigger the first timer event in 500ms
actionTimer.Change(500, Timeout.Infinite);
}
}
private void actionTimer_TimerCallback(object state)
{
lock (driverLock)
{
if (!active) return;
log.Debug("Before event");
StatusEvent(this, new StatusEventArgs()); // it hangs here
log.Debug("After event");
// Now restart timer
actionTimer.Change(500, Timeout.Infinite);
}
}
public void Stop()
{
lock (driverLock)
{
active = false;
}
}
Here is how to reproduce my problem. As I said, the Start and Stop buttons both work, but if you press Start(), and during the execution of the TimerCallback press Stop(), this prevents the TimerCallback to return. It hangs exactly at the same position, the StatusEvent. So the lock is never released and the GUI also hangs, because it's call of the Stop() method cannot proceed.
Now I observed the following: If the application hangs because of this "deadlock" and I click on the application in the task bar with the right mouse button, it continues. It just works as expected then. Anybody has an explanation or better a solution for this?
By the way, I also tried it with InvokeIfRequired as I don't know the internas of the GUI application. This is neccesary if my StatusEvent would change something in the GUI.
Since I have no reference to the GUI controls, I used (assuming only one target):
Delegate firstTarget = StatusEvent.GetInocationList()[0];
ISynchronizeInvoke syncInvoke = firstTarget.Target as ISynchronizeInvoke;
if (syncInvoke.InvokeRequired)
{
syncInvoke.Invoke(firstTarget, new object[] { this, new StatusEventArgs() });
}
else
{
firstTarget.Method.Invoke(firstTarget.Target, new object[] { this, new StatusEventArgs() });
}
This approach didn't change the problem. I think this is because I am Invoking on the main application's event handlers, not on the GUI controls. So the main app is responsible for Invoking? But anyway, AFAIK not using Invoke although needed would not result in a deadlock like this but (hopefully) in an exception.
As for why right-click "unlocks" your application, my "educated guess" of events that lead to this behaviour is as follows:
(when your component was created) GUI registered a subscriber to the status notification event
Your component acquires lock (in a worker thread, not GUI thread), then fires status notification event
The GUI callback for status notification event is called and it starts updating GUI; the updates are causing events to be sent to the event loop
While the update is going on, "Start" button gets clicked
Win32 sends a click message to the GUI thread and tries to handle it synchronously
Handler for the "Start" button gets called, it then calls "Start" method on your component (on GUI thread)
Note that the status update has not finished yet; start button handler "cut in front of"
the remaining GUI updates in status update (this actually happens quite a bit in Win32)
"Start" method tries to acquire your component's lock (on GUI thread), blocks
GUI thread is now hung (waits for start handler to finish; start handler waits for lock; the lock is held by worker thread that marshalled a GUI update call to GUI thread and waits for the update call to finish; the GUI update call marshalled from worker thread is waiting for start handler that cut in front of it to finish; ...)
If you now right-click on taskbar, my guess is that taskbar manager (somehow) starts a "sub-event-loop" (much like modal dialogs start their own "sub-event-loops", see Raymond Chen's blog for details) and processes queued events for the application
The extra event loop triggered by the right-click can now process the GUI updates that were marshalled from the worker thread; this unblocks the worker thread; this in turn releases the lock; this in turn unblocks application's GUI thread so it can finish handling start button click (because it can now acquire the lock)
You could test this theory by causing your application to "bite", then breaking into debugger and looking at the stack trace of the worker thread for your component. It should be blocked in some transition to GUI thread. The GUI thread itself should be blocked in the lock statement, but down the stack you should be able to see some "cut in front of the line" calls...
I think the first recommendation to be able to track this issue down would be to turn on the flag Control.CheckForIllegalCrossThreadCalls = true;.
Next, I would recommend firing the notification event outside of the lock. What I usually do is gather information needed by an event inside a lock, then release the lock and use the information I gathered to fire the event. Something along the lines:
string status;
lock (driverLock) {
if (!active) { return; }
status = ...
actionTimer.Change(500, Timeout.Infinite);
}
StatusEvent(this, new StatusEventArgs(status));
But most importantly, I would review who are the intended clients of your component. From the method names and your description I suspect GUI is the only one (it tells you when to start and stop; you tell it when your status changes). In that case you should not be using a lock. Start & stop methods could simply be setting and resetting a manual-reset event to indicate whether your component is active (a semaphore, really).
[update]
In trying to reproduce your scenario I wrote the following simple program. You should be able to copy the code, compile and run it without problems (I built it as a console application that starts a form :-) )
using System;
using System.Threading;
using System.Windows.Forms;
using Timer=System.Threading.Timer;
namespace LockTest
{
public static class Program
{
// Used by component's notification event
private sealed class MyEventArgs : EventArgs
{
public string NotificationText { get; set; }
}
// Simple component implementation; fires notification event 500 msecs after previous notification event finished
private sealed class MyComponent
{
public MyComponent()
{
this._timer = new Timer(this.Notify, null, -1, -1); // not started yet
}
public void Start()
{
lock (this._lock)
{
if (!this._active)
{
this._active = true;
this._timer.Change(TimeSpan.FromMilliseconds(500d), TimeSpan.FromMilliseconds(-1d));
}
}
}
public void Stop()
{
lock (this._lock)
{
this._active = false;
}
}
public event EventHandler<MyEventArgs> Notification;
private void Notify(object ignore) // this will be invoked invoked in the context of a threadpool worker thread
{
lock (this._lock)
{
if (!this._active) { return; }
var notification = this.Notification; // make a local copy
if (notification != null)
{
notification(this, new MyEventArgs { NotificationText = "Now is " + DateTime.Now.ToString("o") });
}
this._timer.Change(TimeSpan.FromMilliseconds(500d), TimeSpan.FromMilliseconds(-1d)); // rinse and repeat
}
}
private bool _active;
private readonly object _lock = new object();
private readonly Timer _timer;
}
// Simple form to excercise our component
private sealed class MyForm : Form
{
public MyForm()
{
this.Text = "UI Lock Demo";
this.AutoSize = true;
this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
var container = new FlowLayoutPanel { FlowDirection = FlowDirection.TopDown, Dock = DockStyle.Fill, AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink };
this.Controls.Add(container);
this._status = new Label { Width = 300, Text = "Ready, press Start" };
container.Controls.Add(this._status);
this._component.Notification += this.UpdateStatus;
var button = new Button { Text = "Start" };
button.Click += (sender, args) => this._component.Start();
container.Controls.Add(button);
button = new Button { Text = "Stop" };
button.Click += (sender, args) => this._component.Stop();
container.Controls.Add(button);
}
private void UpdateStatus(object sender, MyEventArgs args)
{
if (this.InvokeRequired)
{
Thread.Sleep(2000);
this.Invoke(new EventHandler<MyEventArgs>(this.UpdateStatus), sender, args);
}
else
{
this._status.Text = args.NotificationText;
}
}
private readonly Label _status;
private readonly MyComponent _component = new MyComponent();
}
// Program entry point, runs event loop for the form that excercises out component
public static void Main(string[] args)
{
Control.CheckForIllegalCrossThreadCalls = true;
Application.EnableVisualStyles();
using (var form = new MyForm())
{
Application.Run(form);
}
}
}
}
As you can see, the code has 3 parts - first, the component that is using timer to call notification method every 500 milliseconds; second, a simple form with label and start/stop buttons; and finally main function to run the even loop.
You can deadlock the application by clicking start button and then within 2 seconds clicking stop button. However, the application is not "unfrozen" when I right-click on taskbar, sigh.
When I break into the deadlocked application, this is what I see when switched to the worker (timer) thread:
And this is what I see when switched to the main thread:
I would appreciate if you could try compiling and running this example; if it works the same for you as me, you could try updating the code to be more similar to what you have in your application and perhaps we can reproduce your exact issue. Once we reproduce it in a test application like this, it shouldn't be a problem to refactor it to make the problem go away (we would isolate essence of the problem).
[update 2]
I guess we agree that we can't easily reproduce your behaviour with the example I provided. I'm still pretty sure the deadlock in your scenario is broken by an extra even loop being introduced on right-click and this event loop processing messages pending from the notification callback. However, how this is achieved is beyond me.
That said I would like to make the following recommendation. Could you try these changes in your application and let me know if they solved the deadlock problem? Essentially, you would move ALL component code to worker threads (i.e. nothing that has to do with your component will be running on GUI thread any more except code to delegate to worker threads :-) )...
public void Start()
{
ThreadPool.QueueUserWorkItem(delegate // added
{
lock (this._lock)
{
if (!this._active)
{
this._active = true;
this._timer.Change(TimeSpan.FromMilliseconds(500d), TimeSpan.FromMilliseconds(-1d));
}
}
});
}
public void Stop()
{
ThreadPool.QueueUserWorkItem(delegate // added
{
lock (this._lock)
{
this._active = false;
}
});
}
I moved body of Start and Stop methods into a thread-pool worker thread (much like your timers call your callback regularly in context of a thread-pool worker). This means GUI thread will never own the lock, the lock will only be acquired in context of (probably different for each call) thread-pool worker threads.
Note that with the change above, my sample program doesn't deadlock any more (even with "Invoke" instead of "BeginInvoke").
[update 3]
As per your comment, queueing Start method is not acceptable because it needs to indicate whether the component was able to start. In this case I would recommend treating the "active" flag differently. You would switch to "int" (0 stopped, 1 running)and use "Interlocked" static methods to manipulate it (I assume that your component has more state it exposes - you would guard access to anything other than "active" flag with your lock):
public bool Start()
{
if (0 == Interlocked.CompareExchange(ref this._active, 0, 0)) // will evaluate to true if we're not started; this is a variation on the double-checked locking pattern, without the problems associated with lack of memory barriers (see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)
{
lock (this._lock) // serialize all Start calls that are invoked on an un-started component from different threads
{
if (this._active == 0) // make sure only the first Start call gets through to actual start, 2nd part of double-checked locking pattern
{
// run component startup
this._timer.Change(TimeSpan.FromMilliseconds(500d), TimeSpan.FromMilliseconds(-1d));
Interlocked.Exchange(ref this._active, 1); // now mark the component as successfully started
}
}
}
return true;
}
public void Stop()
{
Interlocked.Exchange(ref this._active, 0);
}
private void Notify(object ignore) // this will be invoked invoked in the context of a threadpool worker thread
{
if (0 != Interlocked.CompareExchange(ref this._active, 0, 0)) // only handle the timer event in started components (notice the pattern is the same as in Start method except for the return value comparison)
{
lock (this._lock) // protect internal state
{
if (this._active != 0)
{
var notification = this.Notification; // make a local copy
if (notification != null)
{
notification(this, new MyEventArgs { NotificationText = "Now is " + DateTime.Now.ToString("o") });
}
this._timer.Change(TimeSpan.FromMilliseconds(500d), TimeSpan.FromMilliseconds(-1d)); // rinse and repeat
}
}
}
}
private int _active;
A couple things come to mind when reviewing your code. The first thing is that you are not checking for a null delegate before firing the status event. If no listeners are bound to the event, then this will cause an exception, which if not caught or handled, might cause strange issues in threaded code.
So the first thing I'd so is this:
if(StatusEvent != null)
{
StatusEvent(this, new StatusEventArgs());
}
The other thing that comes to mind is that perhaps your lock is failing you in some manner. What type of object are you using for the lock? The simplest thing to use is just a plain ole "object", but you must ensure you are not using a value type (e.g. int, float, etc.) that would be boxed for locking, thus never really establishing a lock since each lock statement would box and create a new object instance. You should also keep in mind that a lock only keeps "other" threads out. If called on the same thread, then it will sail through the lock statement.
If you don't have the source for the GUI (which you probably should) you can use Reflector to disassemble it. There is even a plugin to generate source files so you could run the app in your VS IDE and set breakpoints.
Not having access to the GUI source makes this harder, but a general tip here... The WinForm GUI is not managed code, and doesn't mix well with .NET threading. The recommended solution for this is to use a BackgroundWorker to spawn a thread that is independent of the WinForm. Once you're running in the thread started by the BackgroundWorker, you're in pure managed code and you can use .NET's timers and threading for pretty much anything. The restriction is that you have to use the BackgroundWorker's events to pass information back to the GUI, and your thread started by the BackgroundWorker can't access the Winform controls.
Also, you'd be well off to disable the "Stop" button while the "Start" task is running, and vice versa. But a BackgroundWorker is still the way to go; that way the WinForm doesn't hang while the background thread is running.
Yes, this is a classic deadlock scenario. The StatusEvent cannot proceed because it needs the UI thread to update the controls. The UI thread is however stuck, trying to acquire the driverLock. Held by the code that calls StatusEvent. Neither thread can proceed.
Two ways to break the lock:
the StatusEvent code might not necessarily need to run synchronously. Use BeginInvoke instead of Invoke.
the UI thread might not necessarily need to wait for the thread to stop. Your thread could notify it later.
There is not enough context in your snippets to decide which one is better.
Note that you might have a potential race on the timer too, it isn't visible in your snippet. But the callback might run a microsecond after the timer was stopped. Avoid this kind of headache by using a real thread instead of a timer callback. It can do things periodically by calling WaitOne() on a ManualResetEvent, passing a timeout value. That ManualResetEvent is good to signal the thread to stop.
A wild guess here: Could the status message somehow be causing the other app to call your Stop task?
I would put debug stuff at the start of all three methods, see if you're deadlocking on yourself.