views:

2863

answers:

4

I am trying to use the .NET Backgroundworker Object in an application I am developing.

All the material on the internet say that this object runs in the "background" but nowhere have I been able to confirm that this background thread indeed runs in a "low priority" mode. This question arises because in Windows (I assume) a background task can run in a 'normal' or 'below normal' or 'low' priority mode.

In my application, I tried to set the priority myself inside the DoWork function by calling ...

Thread.CurrentThread.Priority=ThreadPriority.Lowest

...

but this seems to have no effect. Does the backgroundworker ignore this call?

I would like to explain some more:

My application is an internet client that collects real-time data on temperature,humidity etc from a chamber and uploads to a web page (not a web service) using

system.net.webclient.UploadValuesAsync(...) calls

I have written the application such that the client GUI collects the data from the chamber, time-stamps them and then queues them for upload like so

...

Synclock objlock
    debug.print("Queueing reading...")
    dataQ.Enque(reading)
End Synclock
...

The backgroundworker's Dowork function dequeues and then uploads like so...

..............

Do
     if dataQ.count() <> 0 then
      Synclock objlock
        reading = dataQ.DeQue()
      End Synclock
      Dim client As New System.Net.WebClient
      ...put the reading in NameValueCollection and upload to server page
      req = new NameValueCollection
      ...
      ...
      client.UploadValuesAsync(uri, "POST", req)
     endif
     thread.sleep(1) 'without this line the CPU usage goes upto 100% and seems to slow other tasks!
    Loop

................

When I run the program I find that whenever the UploadValuesAsync is called the print out the debug window stops. I had also added debug statements to see how many readings are in the queue at any time. It this task is truly run in a low priority, I expected to see the queue count increase rapidly as data is acquired and then decrease only when foreground is idle and data is not being acquired. But this is not the case. As soon as a reading is added to the queue it is dequeued and uploaded. So the queue count is always is either 1 or 0!

Is there something wrong in my approach? Should I not be using the background-worker object at all?

BTW, this is in a dual-core laptop running Windows XP.

+1  A: 

It doesn't claim to be low priority - background means a: not the UI thread, and b: it won't keep a process alive. In reality, it probably relates to ThreadPool threads.

If you want a specific priority thread, then use your own Thread object - but I wouldn't recommend even this normally...

Additionally - "background" doesn't mean "when idle". Even on a single core machine, you will probably see both threads get as much rnutime (if they want it). Even more so on multi-core.

Marc Gravell
The problem is when the background thread is calling the UploadAsync, it seems to be blocking/slowing down the UI thread. I can tell this because the debug statements pause when the upload occurs. How can I avoid this?
Soundar Rajan
How many cores do you have? The work has to happen somewhere...
Marc Gravell
It is a dual core laptop with Win XP.
Soundar Rajan
+4  A: 

Yes, something is wrong with your approach - you're basically tight looping when the queue is empty. Whatever the thread priorities, that's a bad idea.

There's nothing wrong with using a background worker for this, but the enqueuing/dequeuing should really just use a producer/consumer queue which blocks when you try to dequeue when there's nothing ready.

I have an example implementation of a producer/consumer queue in my threading tutorial - see about half way down the linked page. You'll want some way to tell the dequeuing process that it's finished, by the way. (For example, enqueuing a null reference or other special value.) That code was written pre-generics, but it should be easy to update.

Jon Skeet
In your example, you are expecting 10 items in the queue and the consumer thread terminates when it dequeues 10 items. In my case, items are added to the queue throughout the application lifecycle (about 10 items a second) so oWork should never terminate. So what else to do but tight loop?
Soundar Rajan
@Soundar: The only difference there is the termination condition. As I suggested in the answer, you could use a special value (e.g. null) to indicate termination - or just never terminate. The important thing is to block (instead of looping) when there are no entries.
Jon Skeet
Thanks. On further reading of your tutorials, I now know what I did wrong. I should use Monitor.sleep instead of thread.sleep (I was wondering why I needed that anyway). And monitor.wait does seem to work inside the DoWork function.
Soundar Rajan
oops, I meant to write "use Monitor.Wait instead of Thread.sleep" in the comment above.
Soundar Rajan
Yes - Monitor.Wait is the key point here, although you can't just replace your current call to Thread.Sleep - you need to call it while in the lock.
Jon Skeet
+2  A: 

Just to add to what Jon and Marc have already said:

Background threads do not have lower priority. The difference between foreground and background threads is that the CLR will shutdown the process once no more foreground threads are running. Thread pool threads are background threads.

You can actually set the priority of a thread pool thread, but as you have next to no control of which thread pool thread will actually run your task it is not advisable to do so. If you need threads of a specific priority you should create them using the Thread type and set the priority on the instance as desired.

Brian Rasmussen
How come I cannot tag ALL the replies as helpful? Each of them have some helpful suggestions...!
Soundar Rajan
You can only select one answer, but you may up vote all the answers you find helpful.
Brian Rasmussen
A: 

Hi! You might want to look at this worker thread implementation. It has protected constructors for specifying the name of the thread, the priority of the thread and whether or not the thread is a background thread.

http://devpinoy.org/blogs/jakelite/archive/2008/12/20/threading-patterns-the-worker-thread-pattern.aspx

jake.stateresa