views:

360

answers:

6

Hi,

I am using .NET 3.5 and am trying to wrap my head around a problem (not being a supreme threading expert bear with me).

I have a windows service which has a very intensive process that is always running, I have put this process onto a separate thread so that the main thread of my service can handle operational tasks - i.e., service audit cycles, handling configuration changes, etc, etc.

I'm starting the thread via the typical ThreadStart to a method which kicks the process off - call it workerthread.

On this workerthread I am sending data to another server, as is expected the server reboots every now and again and connection is lost and I need to re-establish the connection (I am notified by the lost of connection via an event). From here I do my reconnect logic and I am back in and running, however what I easily started to notice to happen was that I was creating this worker thread over and over again each time (not what I want).

Now I could kill the workerthread when I lose the connection and start a new one but this seems like a waste of resources.

What I really want to do, is marshal the call (i.e., my thread start method) back to the thread that is still in memory although not doing anything.

Please post any examples or docs you have that would be of use.

Thanks.

+1  A: 

I would kill (but end gracefully if possible) the worker thread anyway. Everything gets garbage-collected, and you can start from scratch.

How often does this server reboot happen? If it happens often enough for resources to be a problem, it's probably happening too often.

Robert Harvey
Note: As dthorpe points out, you shouldn't just dump the thread. Try cleaning up as many resources as possible before unloading the thread in the usual manner
Robert Harvey
+1  A: 

You can use the Singleton pattern. In your case, make the connection a static object. Both threads can access the object, which means construct it and use it.

The main thread could construct it whenever required, and the worker thread access it whenever it is available.

Kirk Broadhurst
+1  A: 

Call the method using ThreadPool.QueueUserWorkItem instead. This method grabs a thread from the thread pool and kicks off a method. It appears to be ideal for the task of starting a method on another thread.

Also, when you say "typical ThreadStart" do you mean you're creating and starting a new Thread with a ThreadStart parameter, or you're creating a ThreadStart and calling Invoke on it?

MusiGenesis
This is how I do it in my Windows service, but I run multiple tasks in the background.
Robert Harvey
@Robert: are you saying `QueueUserWorkItem` is overkill for an occasional one-shot task like this? That's probably true, but I'm in the habit of using this because I know I don't have to worry about disposing of the thread involved.
MusiGenesis
QueueUserWorkItem threads are supposed to be used only for short-lived operations. Using the threadpool threads for long-running operations can exhaust the threadpool (finite number of threads) and cause other clients of QueueUserWorkItem in your process to wait a long time before a threadpool thread becomes available.
dthorpe
More info on threads vs. threadpool here: http://stackoverflow.com/questions/230003/thread-vs-threadpool
Robert Harvey
Erk. I really didn't read the question closely enough, sorry. QUWI probably isn't what he needs, but I also don't think it would hurt at all to use it here - he's only going to have one going at a time anyway, so not much chance of exhausting the thread pool.
MusiGenesis
+1  A: 

Have you considered a BackgroundWorker?

From what I understand, you just have a single thread that's doing work, unless the need arises where you have to cancel it's processing.

Stephen Wrighton
+3  A: 

You should avoid killing the worker thread. When you forcibly kill a Win32 thread, not all of its resources are fully recovered. I believe the reserved virtual address space (or is it the root page?) for the thread stack is not recovered when a Win32 thread is killed. It may not be much, but in a long-running server service process, it will add up over time and eventually bring down your service.

If the thread is allowed to exit its threadproc to terminate normally, all the resources are recovered.

If the background thread will be running continuously (not sleeping), you could just use a global boolean flag to communicate state between the main thread and the background thread. As long as the background thread checks this global flag periodically. If the flag is set, the thread can shut itself down cleanly and exit. No need for locking semantics if the main thread is the only writer and the background thread only reads the flag value.

When the background thread loses the connection to the server that it's sending data to, why doesn't it perform the reconnect on its own? It's not clear to me why the main thread needs to tear down the background thread to start another.

dthorpe
A: 

The BackgroundWorker is a bit slower than using plain threads, but it has the option of supporting the CancelAsync method.
Basically, BackgroundWorker is a wrapper around a worker thread with some extra options and events.

The CancelAsync method only works when WorkerSupportsCancellation is set.
When CancelAsync is called, CancellationPending is set.
The worker thread should periodically check CancellationPending to see if needs to quit prematurely.

--jeroen

Jeroen Pluimers