thread restart?

R

Random

I have a thread that I want to start, to process items waiting in a Queue
class, and run in a loop until that Queue is empty. I've got a class set up
to take care of locking issues on the Queue so one thread can add more
things to the Queue while the other is removing and running a process on the
others. But I can't decide how to signal the process Queue items thread to
run. It makes sense to just signal an event every time an item is added to
the Queue, that will in turn set a flag and start the process Queue. Then,
once the Queue is empty, reset the flag (the flag would be to keep me from
trying to restart the process Queue if it already is running).

This is my first multithreading application, so please understand if this
seems like an obvious answer.

Is there another way of doing this that I'm not thinking of? Here's some
code snippets...

Public Class Broadcaster
Inherits System.ServiceProcess.ServiceBase

Private qThread As Thread
Private WithEvents MyTimer As System.Timers.Timer
Private Q As QWrapper

Shared Sub Main().....

Public Sub New().....

Protected Overrides Sub OnStart(ByVal args() As String)
qThread = New Thread(New ThreadStart(AddressOf QProcess))
MyTimer.Interval = 10000
Mytimer.Enabled = True
End Sub

Private Sub MyTimer(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles MyTimer.Elapsed
Dim reader As Thread = New Thread(New ThreadStart(AddressOf QAdd))
reader.IsBackground = True
reader.Start()
End Sub

Private Sub QAdd()
<...code to add items to the Queue in the QWrapper class...>
End Sub

Private Sub QProcess()
<...code to remove and process items to the Queue in the QWrapper
class...>
End Sub
End Class
 
T

Tzim [MVS]

I can't give you the syntax in VB, but here's what I'dd do :
I'd use an infinite loop in the reader thread, and I would Wait for an
AutoReset Event when the queue become empty:
In C#, it would give something like

AutoResetEvent event;
while(true)
{
while(queue.Length==0) event.WaitOne();
Process(queue.Dequeue());
}

then, you'd have to trigger the event by calling event.Set() each time you
add an item to the queue.
With AutoresetEvent, you could also implement a Queue Wrapper with a
blocking call for Dequeue.
But Starting and stopping threads is not very efficient, and should be
avoided.

Tzim
 
R

Random

The main problem here is that I've already written the wrapper class for the
Queue (QWrapper - two methods; Produce adds to the Queue, Consume returns
items from the Queue). I don't want to expose the Count through a method on
the class because then I'd just have another method I'd have to worry about
locking and concurrency issues on.

This is what causes the loop to be a problem - what condition do I check
for? I'm thinking that I can do a "Do Until... Loop" or "While... End
While" loop for as long as my Consume method returns a valid object from the
Queue.

That being said, if I have the process thread declared like I do in the code
I provided (qThread), can I just do qThread.Start() in the QProcess
procedure when I know that items have been added via the QWrapper.Produce
method? Will this work if QProcess has already processed and emptied the
Queue?
 
B

Brian Gideon

Random said:
I have a thread that I want to start, to process items waiting in a
Queue class, and run in a loop until that Queue is empty. I've got
a class set up to take care of locking issues on the Queue so one
thread can add more things to the Queue while the other is removing
and running a process on the others. But I can't decide how to
signal the process Queue items thread to run. It makes sense to
just signal an event every time an item is added to the Queue, that
will in turn set a flag and start the process Queue. Then, once the
Queue is empty, reset the flag (the flag would be to keep me from
trying to restart the process Queue if it already is running).

It sounds like what you're wanting could be easily accomplished with a
blocking queue. In fact, that's almost what you're describing. A
blocking queue can wait on the Dequeue operation until an item appears
in the queue. You can have a thread that executes an infinite loop
that blocks when there's nothing in the queue. There are several
implementations out there for a blocking queue. Be careful because
some may claim to be threadsafe when they really aren't.
This is my first multithreading application, so please understand if
this seems like an obvious answer.

Multithreading is very difficult. Nothing is obvious.
 
R

Random

I'll do some searches using the words "blocking queue", but hadn't turned up
anything useful. All I saw were demos showing a limited run loop.
 
R

Random

Thanks. Actually I based mine on this. I think you'd provided the link on
another post here. It works great, the only issue I had was in creating a
routine that would run the Consume method pretty much continuously without
having a wait event of some kind, or needing to check the status of the
queue (concurrency issues).

I got it working fine by changing the Consume method to return Nothing if
the queue was empty (instead of waiting), and adding a "Produced" event to
the ProducerConsumer class. Then, I just had the Produced event start a
thread that ran a loop retreiving and processing items from the queue until
Nothing was retreived.
 
J

Jon Skeet [C# MVP]

Random said:
Thanks. Actually I based mine on this. I think you'd provided the link on
another post here. It works great, the only issue I had was in creating a
routine that would run the Consume method pretty much continuously without
having a wait event of some kind, or needing to check the status of the
queue (concurrency issues).

I don't think I understand quite what you needed that the class didn't
already provide, really - what's wrong with having a waiting event?
I got it working fine by changing the Consume method to return Nothing if
the queue was empty (instead of waiting), and adding a "Produced" event to
the ProducerConsumer class. Then, I just had the Produced event start a
thread that ran a loop retreiving and processing items from the queue until
Nothing was retreived.

Starting a new thread is likely to be much more expensive than just
waiting - why not just keep one thread ready to consume whatever's
produced?
 
R

Random

I went that route for one reason only... because I needed to have some way,
in my loop that was calling the Consume method, to have it go on ad
infinituum. Although now, it occurs to me all I would need for that is to
have it check a variable that is always true...

Still, from a purist standpoint, it does feel more right to have it
responding to known events instead of being on perpetual hold. Reminds me
of voice message hell, where you call a customer service line and you
navigate through five layers of teleprompts just be be put ON HOLD!!!

Geez, what a time for a rant. What brought that on?

Nevertheless, this way is more flexible in the event I want/need to add more
functionality that needs to check if the thread is actually doing any
processing or is on hold with the Consume method.
 
J

Jon Skeet [C# MVP]

Random said:
I went that route for one reason only... because I needed to have some way,
in my loop that was calling the Consume method, to have it go on ad
infinituum. Although now, it occurs to me all I would need for that is to
have it check a variable that is always true...

Indeed - just keep calling Consume forever, or until you're signalled
to stop in some other way.
Still, from a purist standpoint, it does feel more right to have it
responding to known events instead of being on perpetual hold. Reminds me
of voice message hell, where you call a customer service line and you
navigate through five layers of teleprompts just be be put ON HOLD!!!

Geez, what a time for a rant. What brought that on?

Nevertheless, this way is more flexible in the event I want/need to add more
functionality that needs to check if the thread is actually doing any
processing or is on hold with the Consume method.

You could easily add that functionality in different ways - and waking
up an existing thread is more efficient than creating a new one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top