How to abort a thread started inside another function? - c#

Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,200));
t.Start();
I start a thread named 't' inside the 'Form1_Load' function. I have added a button. When click on that button the thread 't' should stop executing and create a new thread with these parameters.
Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,950));
t.Start();
I know in the form_load event i can use the
t.Abort();

By making t a member of the form, you can reference it later on in the button-click event handler.
Graceful Abort.
Although t.Abort() gets the job done, you might be left with half-processed data in the thread t. You can catch the ThreadAbortException in thread t to gracefully end processing.
Beware of overlap.
The second problem is that your thread might not have aborted yet while your new thread has started already. You can prevent that by calling t.Join() after calling t.Abort().
Hope this helps.

Make Thread t a private member of your form.
public partial class MainForm : Form
{
private Thread t;
}

One way is to make Thread t a global variable (place outside of Form_Load). Then it can be accessed and modified from any method in that class.
To instantiate the thread, use t = new Thread(.....
Before aborting the thread, make sure it is not null.

You need to make the Thread object accessable in both places that you need to access it.
In this case, making it a private varaible would work.
e.g.
public class MyClass
{
private Thread MyThread
{
get;
set;
}
private void myfunc1()
{
MyThread = new Thread(() => moni.CurrUsage(nics,200));
MyThread.Start();
}
private void myfunc2()
{
MyThread.Abort();
// I really need to wait until this thread has stopped...
MyThread.Join();
}
}

Adding to the already given answers:
Note that .Join() will block your current (UI) thread, leaving your application unresponsive to the user.
Just as another take: avoid using .Abort() by using a flag in your Monitor class to exit the task you are doing if possible. You can then still wait for .Join(), but you have full control of the state in the background thread.
public class Monitor
{
private bool _cancel = false;
public void Cancel()
{
_cancel = true;
}
public void CurrUsage(Nics nics, int n)
{
_cancel = false;
// ...
while (!_cancel)
{
// do some stuff
}
}
}
in your Form
private Monitor _monitor { get; set; }
private Thread _t;
public void Button_Click(...)
{
_monitor.Cancel()
_t.Join() // will return as your background thread has finished cleanly
_t = new Thread(() => _monitor.CurrUsage(nics,950));
t.Start();
}

As others have pointed out, all you need in order to call Abort is a reference to the thread (just like any other object in .NET).
However
You should seriously consider rethinking this approach. In general, calling Abort is discouraged, as it does not give the target thread sufficient opportunity to reach a stopping point. While it's sometimes appropriate (or the only option), it's almost always a better idea to ask the target thread to stop (usually through a volatile bool rather than forcing it like this.
For example,
public class ThreadClass
{
private volatile bool stopRequested;
private Thread thread;
public void Start()
{
stopRequested = false;
thread = new Thread(ThreadMethod);
thread.Start();
}
public void Stop()
{
stopRequested = true;
if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not
// completed within 5 seconds
}
private void ThreadMethod()
{
}
}
Your code then goes into ThreadMethod. Within the method, periodically check the value of stopRequested. If it's true, perform whatever cleanup is necessary (if any) and gracefully return out of the thread. If the content is a loop, the general practice is to place the check at the start of the loop (assuming that the loop is sufficiently tight) and exit early if the value is true. The exact placement is really dependent upon the code, but the general idea is that it should be checked often enough to make the thread exit fairly quickly after it gets set, regardless of when that happens.

Related

Detecting if Thread is Alive, or not, with while loop in the safest way c#

I am trying to end my Thread, within the thread, and when aborted, i want to detect that the thread has been aborted (or just, stopped really)
This is what i am doing to do that, but isnt working as it never gets to this part
if (!thread.IsAlive){
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
This is how i'm going about it, thank you for the help. sorry if my question is confusing please ask questions so i can help you help me :) thanks!
public static Thread thread;
public static void 1()
{
thread = new Thread(thread1);
thread.Start();
if (!thread.IsAlive)
{
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
public static void thread1()
{
{
int test = 0;
while (thread.IsAlive){
Console.WriteLine("running.."); // this text will be displayed when the thread is active, and will stop when stopped.
Thread.Sleep(2500);
test += 1;
if (test > 4) // after 4 loops, i want the thread to end itself
thread.Abort();
}
if (!thread.IsAlive){ // once the thread is ended i want it to tell us that, but it never gets to this part.
CommandPrompt.SayMessage("Oops! MBP thread died.");
}
}
}
If you want to check if a thread is still alive, you cannot do that from the code running in that particular thread. Because, if you can execute the code to check if the thread is still alive, it is -- obviously -- still alive. And if the thread is not alive anymore it will -- obviously -- not be able to execute any more code ...
So the only way is to do this from somewhere outside the thread (ie some other thread, maybe even the main thread).
Just schematic code, which is rather clumsy, but will give you a first idea of how you can address this issue. But if there is a third party messing around with your threads, that won't help anything, because what prevents them from killing off your whole application?
public class ThreadTest {
static bool ranToEnd = false;
public static void Main(){
var thread = new Thread(aThread);
var lc = 1;
thread.Start();
while (true){
if (!aThread.IsAlive) {
if (ranToEnd)
Console.WriteLine("aThread terminated normally");
else
Console.WriteLine("aThread ended prematurely");
break;
} else if (++lc == 10) {
aThread.Abort(); //Simulating the abortion of the thread
}
Thread.Sleep(1000);
}
}
public static void aThread() {
//do some work in this thread
// if the thread ran to an end normally, this will be set to true
// if the thread ended prematurely, this will stay false ...
ranToEnd = true;
}
}

Crash from Invoke when MainForm is Disposed in FormClosing

I have an issue that relates to threading, cleaning up unmanaged resources and shutting down my app.
In the main UI thread I have a method that creates a new instance of class Worker. In Worker's constructor I start a new thread that has a while(Scanning) loop that updates some controls in my UI using Invoke() continuously (until Scanning bool is set to false). In the UI thread I raise the event FormClosing() whenever the application is closing down (through X button or Application.Exit() etc.). In FormClosing() I set Scanning to false and do some cleanup of unmanaged resources (that can only be done after the worker thread is done, because it uses those resources. The problem is that when I close the app down the MainForm apparently gets instantly disposed, so the app crashes at the Invoke (because it is trying to make a delegate run from UI thread, but that thread is disposed).
In an attempt to make the worker finish before the UI closes I tried to create a method StopWorker() in the worker class where I put Scanning = false, and then Thread.Join. As you can imagine the Join caused a deadlock as it makes the UI thread sleep but the Invoke needs the UI thread to move on.
In summary I need to cleanup unmanaged resources in FormClosing. I need the worker thread to be done before I do that though, as it uses these resources. The worker thread cannot finish (it uses Invoke) if the MainForm is disposed, therefore creating a tricky situation.
Based on Hans Passant's answer here, I created the below solution. It seems to be working very well.
In UI class/thread:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
var button = sender as Button;
if (button != null && string.Equals(button.Name, #"CloseButton"))
{
//FormClosing event raised by a user-created button action
}
else
{
//FormClosing event raised by program or the X in top right corner
//Do cleanup work (stop threads and clean up unmanaged resources)
if (_bw.Scanning)
{
_bw.Scanning = false;
ClosePending = true;
e.Cancel = true;
return;
}
//Code to clean up unmanaged resources goes here (dummy code below)
ApplicationLogger.Get.Log("Doing final cleanup work and exiting application...");
MemoryHandler.Get.Dispose();
ApplicationLogger.Get.Dispose();
}
}
My worker thread is in another class that has a public bool property called Scanning. It also has this while loop (notice the line at the bottom):
private void Worker()
{
while (Scanning)
{
Thread.Sleep(50);
_sendBackValue[0] = "lbOne";
_sendBackValue[1] = "blaBla";
_synch.Invoke(_valueDelegate, _sendBackValue);
_sendBackValue[0] = "lbTwo";
_sendBackValue[1] = "blaBla";
_synch.Invoke(_valueDelegate, _sendBackValue);
_sendBackValue[0] = "lbThree";
_sendBackValue[1] = "blaBla";
_synch.Invoke(_valueDelegate, _sendBackValue);
}
MainForm.Get.Invoke((Action)(() => MainForm.Get.StopScanning()));
}
Finally, back in the UI class/thread I have this method:
public void StopScanning()
{
if (!ClosePending) return;
ApplicationLogger.Get.Log("Worker thread is closing the application...");
Close();
}
Could you not better use the BackgroundWorker class/control? It is much easier to use because it has already a lot of synchronization stuff in it.
But if you have a separate thread, in your FormClosing event, use:
yourThread.Abort();
yourThread.Join(); // or yourThread.Join(1000); where 1000 is some kind of time out value
in your thread use try-excpet-finally construct
try
{
// do your stuff
}
catch (ThreadAbortException)
{
// do someting when your thread is aborted
}
finally
{
// do the clean up. Don't let it take too long.
}
Note that the Join command will block further execution until the thread has stopped. Therefore, I would recommend a not too high value for the time out parameter, otherwise the user interface will be blocked and will irritate users.
Disclaimer: I do not advocate the use of Thread, ManualResetEvent and, above all, volatile in the .NET 4.5+ era, but since the .NET version was not specified I've done my best to address the problem while keeping things as backwards-compatible as possible.
Here's a solution which uses a polling variable and a ManualResetEvent to block the execution of the FormClosing handler until the loop has completed - without any deadlocks. In your scenario if you have a class-level reference to the Thread which runs the loop, you can use Thread.Join instead of ManualResetEvent.WaitOne in the FormClosing handler - the semantics will be the same.
using System;
using System.Threading;
using System.Windows.Forms;
namespace FormClosingExample
{
public partial class Form1 : Form
{
private volatile bool Scanning = true;
private readonly ManualResetEvent LoopFinishedMre = new ManualResetEvent(false);
private readonly SynchronizationContext UiContext;
public Form1()
{
this.InitializeComponent();
// Capture UI context.
this.UiContext = SynchronizationContext.Current;
// Spin up the worker thread.
new Thread(this.Loop).Start();
}
private void Loop()
{
int i = 0;
while (this.Scanning)
{
// Some operation on unmanaged resource.
i++;
// Asynchronous UI-bound action (progress reporting).
// We can't use Send here because it will deadlock if
// the call to WaitOne sneaks in between the Scanning
// check and sync context dispatch.
this.UiContext.Post(_ =>
{
// Note that it is possible that this will
// execute *after* Scanning is set to false
// (read: when the form has already closed),
// in which case the control *might* have
// already been disposed.
if (this.Scanning)
{
this.Text = i.ToString();
}
}, null);
// Artifical delay.
Thread.Sleep(1000);
}
// Tell the FormClosing handler that the
// loop has finished and it is safe to
// dispose of the unmanaged resource.
this.LoopFinishedMre.Set();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// Tell the worker that it needs
// to break out of the loop.
this.Scanning = false;
// Block UI thread until Loop() has finished.
this.LoopFinishedMre.WaitOne();
// The loop has finished. It is safe to do cleanup.
MessageBox.Show("It is now safe to dispose of the unmanaged resource.");
}
}
}
Now, while this solution is (somewhat) tailored to your description of the problem (which I interpreted to the best of my ability), I had to make a large number of assumptions. If you want a better answer, you'll need to post a concise repro of the problem - not necessarily your production code, but at least a trimmed down working version which still has all the main nuts and bolts in place and exhibits the problem you've described.

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;
}
}
}

Questions about multi-threading

If I have a that thread:
Thread sendMessage = new Thread(new ThreadStart(timer.Start()));
will, the Tick event of the timer will be on the main thread or on the sendMessage thread?
Edit:
I have a queue and i want that every x milisecond the timer will tick and the program will dequeue arrays from the queue, but this is my code:
Thread sendMessage = new Thread(new ThreadStart(startThreadTimer));
public Queue<Array> messageQueue = new Queue<Array>();
System.Threading.Timer timer;
private void startThreadTimer()
{
System.Threading.TimerCallback cb = new System.Threading.TimerCallback(checkIfQueue);
timer = new System.Threading.Timer(cb, null, 4000, 30);
}
private static void checkIfQueue(object obj)
{
}
and I can't call a none static method or use a none static field from the checkIfQueue, and it have to be static, what can i do?
Edit:
Here is the code that one of you sent me, I cahnged him so it fitts to my goal, will it work?
public ConcurrentQueue<Array> messageQueue = new ConcurrentQueue<Array>();
public void Example()
{
var thread = new Thread(
() =>
{
while (true)
{
Array array;
byte[] byteArray = {};
if (messageQueue.Count > 0)
{
messageQueue.TryDequeue(out array);
foreach (byte result in array)
{
byteArray[byteArray.Length] = result;
}
controllernp.Write(byteArray, 0, 100);
}
Thread.Sleep(30);
}
});
thread.IsBackground = true;
thread.Start();
}
It depends on the type of timer. Most timers (System.Timers.Timer or System.Threading.Timer) that can work in a background thread use a ThreadPool thread for their Tick event. In this case, the answer is "neither" thread.
If your timer is a Windows Forms timer or a DispatcherTimer, it will likely cause an exception, since they need to be run on the UI thread, and can't be run on a background thread.
This is going to depend on exactly which timer you are using. The .NET Framework has several timers;
System.Threading.Timer = Could be on any available thread.
System.Windows.Forms.Timer = Should be on the "UI" thread.
System.Timer.Timer = Could be on any available thread.
And probably more that I'm missing.
As mentioned, there are two timers; System.Threading.Timer and System.Windows.Forms.Timer. The first kind may execute on any thread, except the thread you started it from (unless it's part of the threadpool, and your function has returned, then it might be executed there, eventually.)
The second kind, the Windows Forms kind, may execute on either your thread, or another thread. It depends.
The timer needs a window handle, and depending on which thread the handle is created, the Tick event will fire on different threads. The internal window the timer uses is created when it's needed for the first time. Most likely, you have created the timer on the main (GUI) thread, but that will not create the actual window inside the timer. To ensure that the window is created on the main thread you will have to first start, and then stop, the timer at least one time. (It's when started for the first time the window is created.)
(If you didn't get it: the timer uses an internal window to receive the tick event. The window is created on a thread, and that thread needs to have message loop running. The thread that is first to start the timer will create the window, and receive the Tick event. Hopefully that thread is running a messageloop.)
If you are wanting to dequeue items from a queue every X milliseconds then why use a timer at all? It is much easier to spawn a new thread that spins around an infinite loop.
public class Example
{
private ConcurrentQueue<Array> m_Queue = new ConcurrentQueue<Array>();
public Example(int intervalMilliseconds)
{
var thread = new Thread(
() =>
{
while (true)
{
Array array;
while (m_Queue.TryDequeue(out array))
{
// Process the array here.
}
Thread.Sleep(intervalMilliseconds);
}
});
thread.IsBackground = true;
thread.Start();
}
public void Enqueue(Array array)
{
m_Queue.Enqueue(array);
}
}
Update:
No, your method is not thread-safe. The problem is with how you are dequeueing items.
if (messageQueue.Count > 0)
{
messageQueue.TryDequeue(out array);
}
It should really look like this.
if (messageQueue.TryDequeue(out array)
{
}
The TryDequeue method returns false if the queue is empty so it already does the check and dequeue in one atomic operation.

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