What are alternative ways to suspend and resume a thread? - c#

The two methods Thread.Suspend() and Thread.Resume() are obsolete since .NET 2.0. Why? What are other alternatives and any examples?

You'll want to use an AutoResetEvent EventWaitHandle.
Say you want to do something like this (NOTE: don't do this!):
private Thread myThread;
private void WorkerThread()
{
myThread = Thread.CurrentThread;
while (true)
{
myThread.Suspend();
//Do work.
}
}
public void StartWorking()
{
myThread.Resume();
}
Like others have said, this is a bad idea. Even though only using Suspend on its own thread is relatively safe, you can never figure out if you're calling Resume when the thread is actually suspended. So Suspend and Resume have been obsoleted.
Instead, you want to use an AutoResetEvent:
private EventWaitHandle wh = new AutoResetEvent();
private void WorkerThread()
{
while(true)
{
wh.WaitOne();
//Do work.
}
}
public void StartWorking()
{
wh.Set();
}
The worker thread will wait on the wait handle until another thread calls StartWorking. It works much the same as Suspend/Resume, as the AutoResetEvent only allows one thread to be "resumed".

The good alternatives all work by the thread reaching a point where it is happy to wait. Suspend was dangerous because it could suspend the thread while it was holding a lock on a mutex - a recipe for deadlocks.
So what your thread needs is a ManualResetEvent that it can Wait on - at a time when it is safe for it to do so, when it is not holding any locks.

This is the best tutorial ever for Thread (for C#): http://www.albahari.com/threading/
For wait you need to use .Join() on the thread. This will wait until tread finish is job. Other wise you will need to use Wait/Pulse.

you can use ManualReset instead of AutoReset:
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();
Console.WriteLine("Thread started running");
}
public void Pause()
{
_pauseEvent.Reset();
Console.WriteLine("Thread paused");
}
public void Resume()
{
_pauseEvent.Set();
Console.WriteLine("Thread resuming ");
}
public void Stop()
{
// Signal the shutdown event
_shutdownEvent.Set();
Console.WriteLine("Thread Stopped ");
// 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..
Console.WriteLine("Thread is running");
}
}
}

That one is too long. What I need is a quick example codes to use. I found one from the discussion and answered by Mark R. Dawson at http://bytes.com/groups/net-c/458947-thread-suspend. It explains the danger of the obsolete methods and how to use AutoResetEvent to notify the second thread to continue processing.

I agree that is a great tutorial. The main reason Suspend() and Resume() are obsolete is because they are pretty dangerous methods. At any point Thread t could be doing anything. Anything. Imagine your thread is reading a file and has a lock on it. You suspend your thread. File stays locked. Same goes for any other resources. Same goes for a lock on a mutex.

The reasons why Thread.Suspend() and Thread.Resume() are obsolete or removed in .NET are largely the same reasons why Thread.suspend() and Thread.resume() are obsolete in Java. Compare—
Java's thread primitive deprecation FAQ (suspend "is inherently deadlock prone"), with
Mark R. Dawson's answer on .NET's Thread.Suspend()` ("if you stop a thread in mid execution you can run into deadlock and race conditions").

Solution:
Have a thread only resume another thread if the other thread has suspended itself.
Thus, the first thread only resumes the other thread if the other thread suspended itself (ie. its ThreadState = Suspended), and, thus, made itself ready to be resumed. This seems safe & flawless.
Or, am I not understanding .Net threading?

Related

Start and Stop Thread using button [duplicate]

Can anyone give me a headstart on the topic of threading? I think I know how to do a few things but I need to know how to do the following:
Setup a main thread that will stay active until I signal it to stop(in case you wonder, it will terminate when data is received). Then i want a second thread to start which will capture data from a textbox and should quit when I signal it to that of which occurs when the user presses the enter key.
Cheers!
This is how I do it...
public class ThreadA {
public ThreadA(object[] args) {
...
}
public void Run() {
while (true) {
Thread.sleep(1000); // wait 1 second for something to happen.
doStuff();
if(conditionToExitReceived) // what im waiting for...
break;
}
//perform cleanup if there is any...
}
}
Then to run this in its own thread... ( I do it this way because I also want to send args to the thread)
private void FireThread(){
Thread thread = new Thread(new ThreadStart(this.startThread));
thread.start();
}
private void (startThread){
new ThreadA(args).Run();
}
The thread is created by calling "FireThread()"
The newly created thread will run until its condition to stop is met, then it dies...
You can signal the "main" with delegates, to tell it when the thread has died.. so you can then start the second one...
Best to read through : This MSDN Article
Thread th = new Thread(function1);
th.Start();
th.Abort();
void function1(){
//code here
}
Use a static AutoResetEvent in your spawned threads to call back to the main thread using the Set() method. This guy has a fairly good demo in SO on how to use it.
AutoResetEvent clarification

Notifying about task finishing its work

I'm thinking of a simple way of reacting on task finishing its work. I came up with the following solution (paste it to WinForms application with a single button to test):
public partial class Form1 : Form
{
private Thread thread;
public void DoFinishWork() {
// [4]
// UI thread - waiting for thread to finalize its work
thread.Join();
// Checking, if it really finished its work
MessageBox.Show("Thread state: " + thread.IsAlive.ToString());
}
public void DoWork() {
// [2]
// Working hard
Thread.Sleep(1000);
}
public void FinishWork() {
// [3]
// Asynchronously notifying form in main thread, that work was done
Delegate del = new Action(DoFinishWork);
this.BeginInvoke(del);
// Finalizing work - this should be switched
// at some point to main thread
Thread.Sleep(1000);
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
// [1]
// Schedule the task
ThreadStart start = new ThreadStart(DoWork);
// Schedule notification about finishing work
start += FinishWork;
thread = new Thread(start);
thread.Start();
}
}
This is meant to be a simple cancel scenario, so there will be only one thread, which will be running in parallel to the UI thread.
Is there a simpler (or more thread-safe) way of implementing this kind of notification for the Thread?
Please take into consideration two facts:
The only way i can terminate the thread is to Abort it (that's because I have no control over what is being done in the thread - 3rd party code)
Thus, I cannot use BackgroundWorker, because it only provides way of graceful termination.
Is there a simpler (or more thread-safe) way of implementing this kind of notification for the Thread?
Yes, use the TPL and let the framework worry about managing the thread
Task.StartNew(() => {
// do some stuff
}).ContinueWith((task) => {
// do some stuff after I have finished doing some other stuff
});
Or alternatively, since you are working with WinForms, use a BackgroundWorker and handle the RunWorkerCompleted event.
I mistook your notion of kill for cancel - there is no reliable way of actually killing a thread in .NET, even the documentation suggests that using Abort is more or less a gamble and gives absolutely no guarentees that the thread will actually be killed. Also, it will leave the thread and, as a consequence, the application in an unpredictable state so if you are willing to take that risk then that's up to you.
One alternative is to simply let the thread play out but just ignore the results, depending on the size of the task it might not be that big a deal.
Although you need Abort to kill the thread, you can still use the TPL. You could start that thread within the task, and wait for it as well as for an CancellationToken. When the task is cancelled before the thread finishes, you can call Abort on the thread.
It would look something like that:
// In your class:
ManualResetEvent threadFinished = new ManualResetEvent(false);
// In your calling function (button1_Click):
Task.Run( () => {
ThreadStart threadStart = new StreadStart(DoWork);
threadStart += () => { threadFinished.Set(); }
Thread thread = new Thread(threadStart);
threadFinished.Reset();
thread.Start();
WaitHandle waitCancel = cancellationToken.WaitHandle;
int waited = WaitHandle.WaitAny( new WaitHandle[]{ waitCancel, threadFinished } );
if (waited == 0 && cancellationToken.IsCancellationRequested)
thread.Abort();
else
thread.Join()
});

how to pause/resume a thread

How can I pause/resume a thread? Once I Join() a thread, I can't restart it.
So how can I start a thread and make it pause whenever the button 'pause' is pressed, and resume it when resume button is pressed?
The only thing this thread does, is show some random text in a label control.
Maybe the ManualResetEvent is a good choice.
A short example:
private static EventWaitHandle waitHandle = new ManualResetEvent(initialState: true);
// Main thread
public void OnPauseClick(...) {
waitHandle.Reset();
}
public void OnResumeClick(...) {
waitHandle.Set();
}
// Worker thread
public void DoSth() {
while (true) {
// show some random text in a label control (btw. you have to
// dispatch the action onto the main thread)
waitHandle.WaitOne(); // waits for the signal to be set
}
}
I could suggest you to read Threading in C#, by Joe Albahari, particularly Suspend and Resume section:
A thread can be explicitly suspended and resumed via the deprecated methods Thread.Suspend and Thread.Resume. This mechanism is completely separate to that of blocking. Both systems are independent and operate in parallel.
A thread can suspend itself or another thread. Calling Suspend results in the thread briefly entering the SuspendRequested state, then upon reaching a point safe for garbage collection, it enters the Suspended state. From there, it can be resumed only via another thread that calls its Resume method. Resume will work only on a suspended thread, not a blocked thread.
From .NET 2.0, Suspend and Resume have been deprecated, their use discouraged because of the danger inherent in arbitrarily suspending another thread. If a thread holding a lock on a critical resource is suspended, the whole application (or computer) can deadlock. This is far more dangerous than calling Abort — which results in any such locks being released (at least theoretically) by virtue of code in finally blocks.
It's not the best idea to manually suspend and resume threads. However, you can easily simulate this behavior by using thread synchronization primitives (like ManualResetEvent)
Take a look at this question, you may find it helpful.
But I believe you can easily achieve your goal of 'showing random text in a label control' on a time basis by using timers.
Here is a quick example using DispatcherTimer
var timer = new DispatcherTimer();
timer.Tick += (s, e) => Label.Text = GetRandomText();
timer.Interval = TimeSpan.FromMilliseconds(500);
timer.Start();
You can pause it by calling timer.Stop() and then timer.Start() again to resume.
Here's two ways that's worked for me. Both assume that the worker thread has it's own processing loop.
Have the thread invoke a callback to request permission to keep going
Have the parent invoke a method on the thread's class to signal it
The console application example below shows both approaches, using a callback to pause/continue, and a worker method to stop. Another advantage of the callback method is that it's also convenient for passing back status updates while it's checking for permission to continue.
using System;
using System.Threading;
namespace ConsoleApplication7
{
class Program
{
static bool keepGoing;
static void Main(string[] args)
{
keepGoing = true;
Worker worker = new Worker(new KeepGoingDelegate(KeepGoing));
Thread thread = new Thread(worker.DoWork);
thread.IsBackground = true;
thread.Start();
while (thread.ThreadState != ThreadState.Stopped)
{
switch (Console.ReadKey(true).KeyChar)
{
case 'p':
keepGoing = false;
break;
case 'w':
keepGoing = true;
break;
case 's':
worker.Stop();
break;
}
Thread.Sleep(100);
}
Console.WriteLine("Done");
Console.ReadKey();
}
static bool KeepGoing()
{
return keepGoing;
}
}
public delegate bool KeepGoingDelegate();
public class Worker
{
bool stop = false;
KeepGoingDelegate KeepGoingCallback;
public Worker(KeepGoingDelegate callbackArg)
{
KeepGoingCallback = callbackArg;
}
public void DoWork()
{
while (!stop)
{
Console.Write(KeepGoingCallback()?"\rWorking":"\rPaused ");
Thread.Sleep(100);
}
Console.WriteLine("\nStopped");
}
public void Stop()
{
stop = true;
}
}
}

Waking a thread in C#

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

How to Cancel a Thread?

In case of BackgroundWorker, a cancel can be reported by the e.Cancel - property of the DoWork - event handler.
How can I achieve the same thing with a Thread object?
Here is a full example of one way of doing it.
private static bool _runThread;
private static object _runThreadLock = new object();
private static void Main(string[] args)
{
_runThread = true;
Thread t = new Thread(() =>
{
Console.WriteLine("Starting thread...");
bool _localRunThread = true;
while (_localRunThread)
{
Console.WriteLine("Working...");
Thread.Sleep(1000);
lock (_runThreadLock)
{
_localRunThread = _runThread;
}
}
Console.WriteLine("Exiting thread...");
});
t.Start();
// wait for any key press, and then exit the app
Console.ReadKey();
// tell the thread to stop
lock (_runThreadLock)
{
_runThread = false;
}
// wait for the thread to finish
t.Join();
Console.WriteLine("All done.");
}
In short; the thread checks a bool flag, and keeps runing as long as the flag is true. I prefer this approach over calling Thread.Abort becuase it seems a bit nicer and cleaner.
Generally you do it by the thread's execute being a delegate to a method on an object, with that object exposing a Cancel property, and the long-running operation periodically chercking that property for tru to determine whether to exit.
for example
public class MyLongTunningTask
{
public MyLongRunninTask() {}
public volatile bool Cancel {get; set; }
public void ExecuteLongRunningTask()
{
while(!this.Cancel)
{
// Do something long running.
// you may still like to check Cancel periodically and exit gracefully if its true
}
}
}
Then elsewhere:
var longRunning = new MyLongTunningTask();
Thread myThread = new Thread(new ThreadStart(longRunning.ExecuteLongRunningTask));
myThread.Start();
// somewhere else
longRunning.Cancel = true;
A blocked thread can be stopped prematurely in one of two ways:
Thread.Interrupt
Thread.Abort
The main question is if the thread works on any ressources which need to be released correctly - in this case - you need to work with a property on the actual object which runs the thread.
There's Thread.Abort, which works by injecting a ThreadAbortException into the thread. It's a little risky because:
Your thread can get stuck if it's executing native code at the time
The code in the thread better be exception-safe, because this ThreadAbortException could happen on any line of code within it, even something innocent like i = i + 1
You're better off coding your own signalling mechanism between your GUI thread and the background thread. It's hard to recommend something without knowing what's going on inside that thread, but where I have a thread that works by waiting on some object in a loop, I use an AutoResetEvent and wait on that too.

Categories

Resources