Backgroundworker abort - c#

I recently tried to use backgroundworker instead of "classic" threads and I'm realizing that it's causing, at least for me, more problems than solutions.
I have a backgroundworker running a synchronous read (in this case from serialPort) and getting blocked around 30 seconds in 1 code line, then cancellationpending isn't the solution. I'm seeing that if the application gets closed at this point (either with the cross button and Application.Exit()) the process keeps zombie forever.
I need a way to force abort or to kill the backgroundworker thread.

I put one together that (i think) does the job. Please let me know if im waaaay off.
Here is a simple exaple of how it works.
var backgroundWorker = new BackgroundWorker(){WorkerSupportsCancellation = true};
backgroundWorker.DoWork += (sender, args) =>
{
var thisWorker = sender as BackgroundWorker;
var _child = new Thread(() =>
{
//..Do Some Code
});
_child .Start();
while (_child.IsAlive)
{
if (thisWorker.CancellationPending)
{
_child.Abort();
args.Cancel = true;
}
Thread.SpinWait(1);
}
};
backgroundWorker.RunWorkerAsync(parameter);
//..Do Something...
backgroundWorker.CancelAsync();
Since the background worker is part of the thread pool, we dont want to abort it. But we can run a thread internally which we can allow an abort to occur on. The backgroundWorker then basically runs until either the child thread is complete or we signal to it to kill the process. The background worker thread can then go back into the read pool. Typically I will wrap this up in a helper class and pass through the delegate method that I want the background thread to run passed in as the parameter and run that in the child thread.
Please someone let me know if im banging my head against a wall but it seems to work fine.. But thats the problem with threads isnt it.. the varying results you can get when you run it at different times.

The process should not become a zombie, since the BackgroundWorker thread is marked as "background" and should end when the UI is closed.

I'm not very sure on what you're trying to accomplish, but maybe the SerialPort.DataReceived event is a better solution?
If you're already proficient with the usage of threads, I don't see the point in using BackgroundWorker. It's designed for people who don't understand threads in the first place.
Besides, I don't like the idea of aborting a thread. It feels dangerous, and multithreaded applications don't need any more risk taking.

I don't think the BackgroundWorker supports killing of the thread. Cancelling an operation must be done in the method that performs the job. In your case I think a regular thread will be the best option.

You can try this:
backgroundworker.Dispose();
backgroundworker = null;
GC.Collect(); //this helps cleans up ram

Related

Waiting for and terminating a thread after a given time without blocking in .NET 3.5

I have a WinForms application on .NET 3.5. In this form, the user triggers an operation which is executed in another thread (a BackgroundWorker to be precise) so as to not block the UI thread. I'm in MVP, so all this is being done by a presenter which interacts with an interface to the view (implemented by the Windows Form). So far so good.
I would like to introduce functionality whereby a timeout period is introduced for the background operation to complete before cancelling it. Sounds simple enough. But the background operation calls a single function on a third-party component which may never return, so the cancellation capabilities of the BackgroundWorker are of no use to me here. Also, the BackgroundWorker.RunWorkerCompleted allowed me to get back on the UI thread, so I need to wait for the timeout or success and be able to get back to my calling thread (namely the UI thread).
I tried this using a plain old Thread (which does support Abort()) and a Timer running on a second thread, but can't seem to get it to work quite right since Join() is blocking my UI thread despite the description stating that it will block "while continuing to perform standard COM and SendMessage pumping". Admittedly I assumed this implied that it would continue to process Windows Messages, which was not the case.
int timeoutInMsec = 10000;
Thread connectThread = new Thread(Connect);
Thread timerThread = new Thread(() =>
{
var timer = new System.Windows.Forms.Timer() { Interval = timeoutInMsec };
timer.Tick += (_s, _e) =>
{
timer.Stop();
if (connectThread.ThreadState == ThreadState.Running)
connectThread.Abort();
};
};
connectThread.Start();
timerThread.Start();
timerThread.Join();
connectThread.Join();
Based on this question, I tried removing the second timer thread and adding a ManualResetEvent and calling Set() when the timer ticked, or when the Connect method did indeed complete. Here, instead of Join I used WaitOne, but unfortunately this also blocks my UI thread. I also found this other question, which a CancellationTokenSource which unfortunately is not available in .NET 3.5.
So, how can I spin my worker up and be able to terminate it after a given amount of time in .NET 3.5, while at the same time be able to get back to the thread where I spun up the worker thread to execute a sort of OnCompleted handler?
Many thanks in advance!
PS: I don't have a lot of experience in multi-threaded programming in .NET, so I'm sorry if this is trivial.
If I understood your question correctly, the following algorithm should solve your problem:
As before, create a BackgroundWorker to do your background work.
In BackgroundWorker_DoWork,
create a new thread (let's call it the "third-party thread") to call your third-party library, and then
wait for the third-party thread to finish or the timeout to elapse. (*)
That way, your UI won't block, since only the Backgroundworker thread is waiting, not the main thread.
Now about the interesting part: How do you wait for the third-party thread to finish (the step marked with (*))?
My suggestion would be to simply use "loop waiting with sleep", i.e. (pseudo-code, you can use the Stopwatch class for the timeout):
do until (third-party thread has finished or x seconds have elapsed):
Thread.Sleep for 100ms
if third-party thread has not finished:
Abort it // we don't have another choice
else
Process the result
It's not best practice, but it's simple, it gets the job done and you can always replace it with fancy cross-thread-syncronization stuff (which is non-trivial to get right) once you got it all working.
It's useless to create a Forms.Timer on a non-gui thread. Don't create it on a separate thread. Why are you Joining the threads? The usage of Join is to block the current thread until the other thread is finished.
This is untested pseudo code, this is for example purpose.
public class Form1: Form1
{
private int timeoutInMsec = 10000;
private System.Windows.Forms.Timer _timer;
private Thread _connectThread;
public Form1()
{
_connectThread = new Thread(Connect);
_connectThread.Start();
_timer = new System.Windows.Forms.Timer() { Interval = timeoutInMsec };
_timer.Tick += (_s, _e) =>
{
_timer.Stop();
if (_connectThread.ThreadState == ThreadState.Running)
_connectThread.Abort();
};
};
}
private void Connected()
{
}
private void Aborted()
{
}
private void Connect()
{
try
{
DoConnect3rdPartyStuff();
this.Invoke(Connected);
}
catch(ThreadAbortException)
{
// aborted
this.Invoke(Aborted);
}
}
}

End a thread conformation

So I'm still fairly new to C#. Im learning about threads.
So far I would like to know how to check if a thread has ended. I know that i can put a bool at the end of the method the thread uses and use that to determine if the thread ends.. but i dont want to do that, mainly because i want to learn the right way
so far I have this.
Thread testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
I read about the thread.join(); class. To my understanding, that class only prevents any code after that from executing.. Please help
Well there are different ways that give different results
1 ) Wait until the work has finished. This is exactly what you've got with your code already. You'll start a thread and then wait for that thread to finish before continuing execution.
thread.Start();
thread.Join();
2) thread.ThreadState will tell you whether or not the thread has finished. In a basic scenario you could do the following. This would allow you to check the current thread state at any point in your code where you've got access to the state.
if(thread.ThreadState != ThreadState.Running){
// Thread has stopped
}
3) Using an event. A lot of Async examples will start some work and then trigger an event once the work has been completed. In this way you can sit watching for an event and respond once the work has completed. A usage example may look like the WebClient class
WebClient client = new WebClient();
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
Thread.Join() Blocks the thread you call it on until the thread you have called Join() on returns. Extending the example you have above:
Thread testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
//Do more stuff here. This stuff will not start until testThreadd has completed its work.
you can do this
public partial class MainWindow : Window
{
Thread testThreadd;
public MainWindow()
{
InitializeComponent();
testThreadd = new Thread(Testmethod);
testThreadd.Start();
testThreadd.Join();
}
public void Testmethod()
{
// begining your treatement
// Ending your treatement
this.testThreadd.Abort();
}
}
Thread.Join method pauses current thread execution until second thread completes. It serves for thread synchronization and it's well enough indicator.
Otherwise, you should use Thread.IsAlive property to check if thread is running while not interrupting current thread. This property covers any state between Thread.Start and the end of the thread.

Thread Termination suggestion required

I am using BackgroundWorker for processing a long running external operation. However the user have option to cancel the background operation. Since my custom BackgroundWorker supports Thread.Abort(), all I am doing is BackgroundWorker.Abort() when user triggers Cancel from main thread.
But the thread is not actually terminating, it is still completing the external process. Is there any way I can terminate a thread instantly.
I do not have control on the external processing, so cannot send any flag for approach like while (checkThreadCancelled){}.
Below is my pseudo code.
Any help?
AbortableBackgroundWorker _bgWorker;
void MainThreadFunc()
{
_bgWorker = new AbortableBackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(bg_DoWork);
_bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
( bg_RunWorkerCompleted );
_bgWorker.WorkerSupportsCancellation = true;
_bgWorker.RunWorkerAsync();
}
void bg_DoWork()
{
//Call external dll function for processing
}
void bg_RunWorkerCompleted()
{
//Process completed code
}
void CancelBgProcess()
{
if(_bgWorker != null)
_bgWorker.Abort();
}
The Abort method relies on worker thread cooperating with it. Ultimately it causes the CLR to throw an exception indicating that the thread is to abort, which the thread is free to deal with as it pleases.
As your worker thread is executing something in a DLL, the CLR isn't in control and therefore it does not have the option to throw an exception.
You have the option of using the Win32 TerminateThread API, but doing so is severe and may or may not lead to corruption within your process. TerminateThread is not really an option that you should ever choose.
Since you cannot modify the library that you are calling, you are left with two options. The first and easiest approach, lower the priority of the background thread and ignore the fact that it continues to run after cancellation.
The second is to launch your background operation in a separate process rather than thread. At which point, you may terminate the entire process if the operation is cancelled. If you go this route, you will need to pick some form of IPC to communicate the input and output parameters of the library.
Tasks and CancellationTokens ultimately will not help you in this situation as you will end up in the same place: executing library code that will not cooperate with you in order to be cancelled.
You don't want to use Thread.Abort, it is typically considered bad practice. There are many questions asked on SO that provide some very good explanations. For example: Timeout Pattern - How bad is Thread.Abort really?
Try looking at Tasks and CancellationTokens. See this MSDN article: http://msdn.microsoft.com/en-us/library/dd997396.aspx
Try this:
if (_bgWorker.IsBusy)
{
_bgWorker.WorkerSupportsCancellation = true;
//To cancel the Thread if Closing the Application
//while the Background Thread Worker is Still running on Background.
_bgWorker.CancelAsync();
}
It will stop the current thread process and will cancel the ongoing operation on that thread.
May be it helps you

c# sleeping thread problem

what is the problem in the code part below? Any ideas? I m sending command to my device through serial port. After each command the device will work for this command and then the other command comes for it and continues like this.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
I figured out if i erase second sleep and function3 from the code like below, it does both two function but if i want to continue like this way it does not do the third one.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
}
works...
Thank you
You're blocking the UI thread. Don't do that. It means your UI can't update itself. Instead, set a System.Windows.Forms.Timer to fire in 5 seconds with the next function to call. Alternatively, do all of this in a different thread entirely (possibly using Sleep, possibly using another kind of timer to fire on a thread-pool thread) and use Control.Invoke/BeginInvoke to marshall back to the UI thread when you need to update the UI itself.
EDIT: Given your "answer", it seems that blocking the UI thread was only one of the problems - and getting the device to respond properly at all is a bigger problem. You shouldn't just rely on sleeping for a certain amount of time. You should detect when the device has completed the previous command. It's possible that it doesn't give any feedback, but that would be horrifically poor design. If at all possible, investigate how to read feedback from the device as to when it's finished (e.g. reading from the serial port!) and only start the next command when the previous one has finished. Depending on how you receive the feedback, you could use a blocking call on a non-UI thread, or use an asynchronous model to trigger things.
The BackgroundWorker might be a solution to solve the blocking of the UI.
Get rid of the Sleeps If the functions are creating their own threads, give them callback methods that trigger the next function after the first has finished.
As the code is presented there it is nothing wrong with it. It will:
Execute function 1
Sleep 5 seconds
Execute function 2
Sleep 5 seconds
Execute function 3
However since this is on a GUI event it will freeze the application while doing so. Consider spinning off the execution into a thread instead.
In .Net 4.0:
Task.Factory.StartNew(() => sendData());
In all .Net versions:
System.Threading.Thread myThread = new System.Threading.Thread(sendData);
myThread.IsBackground = true;
myThread.Start();
And then you have your sendData method:
private void sendData()
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
If you really need to do stuff in the GUI thread you can make it more responsive by regularly calling Application.DoEvents();, but this is not a good way of solving it.
Also remember that you can't access the GUI from other threads. See http://kristofverbiest.blogspot.com/2007/02/simple-pattern-to-invoke-gui-from.html for sample code on how to invoke the GUI thread from other threads.
Thank you guys. I solve it. The problem is i did not make thread sleep enough. 5000 ms do not enough for the second command.

Restarting a thread in .NET (using C#)

I'm looking for a way to restart a thread that has been stopped by Abort()..
public partial class MyProgram : Form
{
private Thread MyThread = new Thread(MyFunction);
private System.Windows.Forms.Button startStopBtn = new System.Windows.Forms.Button();
public MyProgram()
{
MyThread.Start();
startStopBtn += new EventHandler(doStop);
startStopBtn.Text = "Stop";
}
private static void MyFunction()
{
// do something
}
private void doStop(object sender, EventArgs e)
{
MyThread.Abort();
startStopBtn -= new EventHandler(doStop);
startStopBtn += new EventHandler(doStart);
startStopBtn.Text = "Start";
}
private void doStart(object sender, EventArgs e)
{
MyThread.Start(); // << Error returned when clicking the button for 2nd time
startStopBtn -= new EventHandler(doStart);
startStopBtn += new EventHandler(doStop);
startStopBtn.Text = "Stop";
}
}
Any idea?
Once you have aborted your thread, you cannot start it again.
But your actual problem is that you are aborting your thread. You should never use Thread.Abort().
If your thread should be paused and continued several times, you should consider using other mechanisms (like AutoResetEvent, for example).
[EDIT]
The simplest solution to abort a thread, as mentioned by Ian Griffiths in the link above, is:
The approach I always recommend is dead simple. Have a volatile bool field that is visible both to your worker thread and your UI thread. If the user clicks cancel, set this flag. Meanwhile, on your worker thread, test the flag from time to time. If you see it get set, stop what you're doing.
The only thing that you need to do to make it work properly, is to rearrange your background method so that it runs in a loop - so that you can periodically check if your flag has been set by a different thread.
If you need to have pause and resume functionality for the same worker thread, instead of the simple volatile bool flag approach, you could go for a slightly more complex approach, a synchronizing construct such as AutoResetEvent. These classes also provide a way to put the worker thread to sleep for a specified (or indefinite) amount of time between signals from the non-worker thread.
This thread contains a concrete example with Start, Pause, Resume and Stop methods. Note how Brannon's example never aborts the thread. It only fires an event, and then waits until the thread finishes gracefully.
Simply add MyThread = new Thread(MyFunction) before calling MyThread.Start() in doStart(). Do not create the thread outside of your methods, the space there is thought for declarations.
Please note that killing a thread with thread.Abort() can be very dangerous, as it might cause unexpected behavior or might not correctly dispose resources owned by the thread. You should try to accomplish clean multi threading, like Groo described in his answer.
The simple answer is, you can't. Once a thread has been aborted, you can't restart it. Just create a method or something, that returns a Thread object just how you need it. When you need a new Thread, just get it from that method.
No, there isn't, but why would you want to? Just start up a new thread, with the same ThreadStart, and the same parameter (if any).
If you really need to interrupt the thread function and resume, you should set a condition and then check it periodically during processing.
That would allow you to stop processing for some amount of time and then resume.
I've used events and Wait calls to accomplish a similar task.
The easiest way is to not abort the thread.
I really don't understand why people provide information if they do not know that is correct..
How can a real programmer suspend or stop processing a thread for sometime and then release it and thereby making the code vulnerable...
#Brad-- m sorry.. but your idea was not good..
#Rhythmic - You need to work on your way to approach things..
BFree was somewhat right if you people got him the same way he wanted to say..
You just need to re-declare that..
below is the example:
Public Shared Sub ResetAbort()
Dim ThreadPleaseWait As New Thread(New ThreadStart(AddressOf YourSubName))
YourThreadName.Start()
Thread.Sleep(2000)
YourThreadName.Abort()
End Sub
Now you can use this Sub anywhere you want to start the thread. It will automatically abort the thread.
If you want to start the thread on Button1_click() event and stop it on Button2_Click() event use this:
in Button1_click() event
Dim ThreadPleaseWait As New Thread(New ThreadStart(AddressOf YourSubName))
YourThreadName.Start()
in Button2_click() event
YourThreadName.Start()
doing this way you will abort you thread where ever you want and will initialize it again.
You can also use YourThreadName.ThreadState.Running property to check if the thread is running or not(Just to avoid multiple instances of the same thread.....

Categories

Resources