views:

1091

answers:

4

Hi,

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.

A: 

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.

Rune Grimstad
+2  A: 

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.

DonkeyMaster
I've found SerialPort.DataReceived to be a bit confusing in CF, don't know if the impl is better in FF. The CF one uses more threads than you would expect so watch out.
Quibblesome
Almost tempted to -1 for the comment about the BackgroundWorker; it's designed to enforce some standards and automatically marshal events to the UI thread, which are valid reasons for its usage; not understanding threading will cause problems no matter which way you go.
Alex Paven
A: 

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

uli78
A: 

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.

Rob