Waiting on a Thread - Revisited

C

Cor Ligthert

Then, the couple start to make love, and the
other passengers just put their heads down and become ever more engrossed in
their reading matter.

Yes really a difference with here, probably here somebody stends up and asks
if he can help?

Cor
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
You are right the word is queue, however for me a stack is a first In first
Out queue and I am using for a First In First Out queue as well the word
stack, however queue should be the word.

That's something to watch out for in future then - stacks are generally
last-in-first-out (like a stack of plates - you put a plate on the top,
and take it off the top too).

Hence System.Collections.Stack :)

I have every sympathy with those coming to computing without English as
a native language. Life's hard enough without having to do translation
the whole time! Even though I sometimes find your English hard to
understand, it's certainly a lot better than my grasp of any other
language...
 
C

Charles Law

Ok, I'm back. Who said this was going to be easy (actually, no one, I
think).

As usual, it's not as straight forward as I am going to describe, but this
illustrates the problem.

I have two threads: the UI thread and a polling (worker) thread. The polling
thread goes round and round updating the UI with information it reads from a
serial port, based on messages it reads from a queue. Before it reads from
the queue, it gets a lock on it (SyncLock) to synchronise adding and
removing items. If the queue contains a message it is removed, the serial
port is read, the UI is updated, and the lock is released (End SyncLock).

The UI sits happily, displaying the latest information.

Because the polling thread is not the UI thread (obviously) it can't just
stuff things onto the screen. So, when it updates a textbox, for example, it
uses a delegate and calls Textbox1.Invoke. Great ... fine, so far.

Now, the user comes along (bless him), and clicks a button. This is the
signal that a message must be added to the queue. So, the UI calls a method
to add a message to the queue. Before accessing the queue, the UI thread
gets a lock on the queue, adds its message, pulses the queue, and releases
the lock. Still sounding good.

However, when the UI thread trys to get the lock (SyncLock again) it can't
get it straight away, because the polling thread has a lock, and is about to
update the UI. Therefore, the UI thread waits patiently for the lock.

The polling thread, meanwhile, goes to update the UI. It finds it is not on
the UI thread, so sets up the delegate and calls Invoke ... and is never
heard from again.

Invoke hangs because it is now trying to marshal onto the UI thread, but the
UI thread is waiting on a lock that the polling thread holds, so we have
deadlock.

Over to you Jon / Cor / anyone :-(

Charles
 
J

Jon Skeet [C# MVP]

Charles Law said:
Ok, I'm back. Who said this was going to be easy (actually, no one, I
think).

As usual, it's not as straight forward as I am going to describe, but this
illustrates the problem.

I have two threads: the UI thread and a polling (worker) thread. The polling
thread goes round and round updating the UI with information it reads from a
serial port, based on messages it reads from a queue. Before it reads from
the queue, it gets a lock on it (SyncLock) to synchronise adding and
removing items. If the queue contains a message it is removed, the serial
port is read, the UI is updated, and the lock is released (End SyncLock).

I think I can see what is coming...
The UI sits happily, displaying the latest information.

Because the polling thread is not the UI thread (obviously) it can't just
stuff things onto the screen. So, when it updates a textbox, for example, it
uses a delegate and calls Textbox1.Invoke. Great ... fine, so far.

Now, the user comes along (bless him), and clicks a button. This is the
signal that a message must be added to the queue. So, the UI calls a method
to add a message to the queue. Before accessing the queue, the UI thread
gets a lock on the queue, adds its message, pulses the queue, and releases
the lock. Still sounding good.

However, when the UI thread trys to get the lock (SyncLock again) it can't
get it straight away, because the polling thread has a lock, and is about to
update the UI. Therefore, the UI thread waits patiently for the lock.

The polling thread, meanwhile, goes to update the UI. It finds it is not on
the UI thread, so sets up the delegate and calls Invoke ... and is never
heard from again.
Indeed.

Invoke hangs because it is now trying to marshal onto the UI thread, but the
UI thread is waiting on a lock that the polling thread holds, so we have
deadlock.

Over to you Jon / Cor / anyone :-(

Well you've done a first rate job of analysing the problem. All you
need to do now is move the call to the UI update out of the lock, and
you're home free :)

Limit yourself to only holding the lock while you absolutely have to -
for interacting with the queue. When you've read from the queue,
release the lock and *then* do whatever you need to with the object
you've just fetched, eg update the UI.
 
A

AlexS

Hi, Charles

Do you really need to read port and call Invoke from non-UI thread inside
lock? As I see it, you need lock only for queue. Rule of thumb is - free
objects as soon as you can. So, release it immediately after getting message
from queue.

HTH
Alex
 
C

Charles Law

Hi Jon / Alex

Hmm. I know you're right ... but ...

I deliberately kept the whole 'read message / update UI' thing inside the
SyncLock construct because it served as a way of pacing outgoing messages.

Messages have to be sent out synchronously, and the polling thread is
capable of adding messages to the queue much faster than they can be sent.
Therefore, locking the queue whilst the message was being sent seemed a
convenient way of preventing a backlog of messages from building up in the
queue. However, when the user clicks something, their request takes
precedence over the background processing, so it is legitimate to insert the
message at the head of the queue and not have to wait.

Can you think of another way round this?

Charles
[If my spelling has started to awry it is because I have started using
OE-QuoteFix, and now the spell checker always passes, regardless of spelling
mistakes.]
 
C

Cor Ligthert

Hi Charles,

A while back that I was busy with threads, however I have not so much
synclocks as that I started the first time with threads, by just passing the
values from the queue (what a terrible word is that) to the thread and not
the biljartstick (before you correct queue) I did overcome those problems.

However I do not know of course if that is possible for you.

Cor
 
J

Jon Skeet [C# MVP]

Charles Law said:
Hmm. I know you're right ... but ...

I deliberately kept the whole 'read message / update UI' thing inside the
SyncLock construct because it served as a way of pacing outgoing messages.

Messages have to be sent out synchronously, and the polling thread is
capable of adding messages to the queue much faster than they can be sent.
Therefore, locking the queue whilst the message was being sent seemed a
convenient way of preventing a backlog of messages from building up in the
queue. However, when the user clicks something, their request takes
precedence over the background processing, so it is legitimate to insert the
message at the head of the queue and not have to wait.

Can you think of another way round this?

When you send the message, you can always make the worker thread then
sleep for a short time, so that it's then ready to send or receive
again. If messages are queued faster than they're going to be sent,
there's bound to be a backlog *somewhere* - and in the queue is
probably the best place for them.
 
C

Charles Law

Hi Cor
the thread and not the *biljartstick* (before you correct queue) I did

You've got me with this one. I'm not familiar with the word '"biljartstick".

Is is something like a snooker cue?

Charles
 
C

Charles Law

Hi Jon

I nearly added ... I don't want to add any artifical pacing because the
timing will be purely arbitrary ... but I didn't.

The number of messages being sent by the polling thread is not important,
only that they should be sent without gaps. The polling messages are all he
same, so all I need to do is ensure that there is always a polling message
waiting to be sent, but no more.

Charles
 
J

Jon Skeet [C# MVP]

Charles Law said:
I nearly added ... I don't want to add any artifical pacing because the
timing will be purely arbitrary ... but I didn't.

The number of messages being sent by the polling thread is not important,
only that they should be sent without gaps. The polling messages are all he
same, so all I need to do is ensure that there is always a polling message
waiting to be sent, but no more.

I'm not sure I follow, I'm afraid. How can you determine when you can
next send a message? It sounds like that's the crux of the problem.
 
C

Charles Law

I just need a continuous stream of polling messages to be sent out. Each new
message can be sent when the last one has been acknowledged (by the remote
end). However, the user can add a non-polling message to the queue, in which
case that is sent amid the stream of polling messages.

Charles
 
C

Cor Ligthert

Hi Charles,

Yes cue, I don't know why, however for me it is sounds always something the
same as queue when I hear those guys (that commenter you know the one with
that shiny head) on BBC talking when there is snooker. (However maybe I
think about that).

Cor
 
J

Jon Skeet [C# MVP]

Charles Law said:
I just need a continuous stream of polling messages to be sent out. Each new
message can be sent when the last one has been acknowledged (by the remote
end). However, the user can add a non-polling message to the queue, in which
case that is sent amid the stream of polling messages.

In which case, the synchronization you need is between the polling
thread and the acknowledgement. You might want to do this with events,
for instance, firing an event whenever an acknowledgement is received,
and subscribing to that event with a delegate which adds a message to
the queue - possibly only if there isn't one there already.
 
C

Charles Law

Hi Jon

You certainly appear to have grasped the nub of the problem. But I am guilty
of misleading in one respect.

When I said that the polling messages are all the same, I wasn't quite
telling the truth. They rotate round about 16 different messages, so the
first poll is type 1, the second type 2, and so on, up to 16. Then they
start again. The sequence is important, and there must not be any omissions.
So I do need to carefully synchronise the polling with the acknowledgements,
as well as the intermittent UI messages.

I like the idea of using an event to get the next polling message (rather
like the TxBufferEmpty interrupt from a UART). I am also looking at creating
a dedicated queue class to maintain the messages, rather than use the
standard Queue class, in particular to allow me to insert messages ahead of
any polling messages (something the standard class doesn't allow). For this
reason, I am inheriting from CollectionBase rather than Queue, unless you
know of a better one.

Charles
[By the way, thanks for your continued help]
 
J

Jon Skeet [C# MVP]

Charles Law said:
You certainly appear to have grasped the nub of the problem. But I am guilty
of misleading in one respect.

When I said that the polling messages are all the same, I wasn't quite
telling the truth. They rotate round about 16 different messages, so the
first poll is type 1, the second type 2, and so on, up to 16. Then they
start again. The sequence is important, and there must not be any omissions.
So I do need to carefully synchronise the polling with the acknowledgements,
as well as the intermittent UI messages.

Right. That suggests having a concept of a "next polling message" - but
you only add that to the queue if the queue is empty at the time (or
maybe if it only has, say, fewer than 3 entries).
I like the idea of using an event to get the next polling message (rather
like the TxBufferEmpty interrupt from a UART). I am also looking at creating
a dedicated queue class to maintain the messages, rather than use the
standard Queue class, in particular to allow me to insert messages ahead of
any polling messages (something the standard class doesn't allow). For this
reason, I am inheriting from CollectionBase rather than Queue, unless you
know of a better one.

Inheriting from CollectionBase sounds like a fine idea to me.
 
A

AlexS

Hi, Charles

couple (triple) of comments
- queue can serve as starting point - you post there initial (starting)
message and user messages only
- thread checks the queue and processes next message. If it is user one -
you get what you want (you can send it) and don't need to hold lock on queue
anymore.
If it is <start poll> message - it sends first poll message and saves state
in internal member.
- when message was sent and processed thread locks queue once again and
checks if there are any message requests. If yes - they are user ones and
must be sent. If not, queue can be unlocked and thread can check state -
should it send next poll message or not.

In this scenario you don't need to hold queue for long periods of time.
Scheme could be expanded with arbitrary number of message sequences. It
reminds me a bit job scheduler, don't you agree?

HTH
Alex

Charles Law said:
Hi Jon

You certainly appear to have grasped the nub of the problem. But I am guilty
of misleading in one respect.

When I said that the polling messages are all the same, I wasn't quite
telling the truth. They rotate round about 16 different messages, so the
first poll is type 1, the second type 2, and so on, up to 16. Then they
start again. The sequence is important, and there must not be any omissions.
So I do need to carefully synchronise the polling with the acknowledgements,
as well as the intermittent UI messages.

I like the idea of using an event to get the next polling message (rather
like the TxBufferEmpty interrupt from a UART). I am also looking at creating
a dedicated queue class to maintain the messages, rather than use the
standard Queue class, in particular to allow me to insert messages ahead of
any polling messages (something the standard class doesn't allow). For this
reason, I am inheriting from CollectionBase rather than Queue, unless you
know of a better one.

Charles
[By the way, thanks for your continued help]

In which case, the synchronization you need is between the polling
thread and the acknowledgement. You might want to do this with events,
for instance, firing an event whenever an acknowledgement is received,
and subscribing to that event with a delegate which adds a message to
the queue - possibly only if there isn't one there already.
 
C

Charles Law

Hi Alex

All the comments are useful and appreciated. I am trying to think of a way
for the queue object to block the polling thread until the queue is empty
when it tries to add a message, but allow messages from the UI thread to be
added to the queue immediately without blocking. If I can make it all
internal to the queue class then the queue can manage itself, rather than
rely on correct implementation in the external code where messages are added
and removed. The queue will also remove non-polling messages from the queue
first, when its DeQueue method is called, and then any remaining polling
messages.

Charles

Hi, Charles

couple (triple) of comments
- queue can serve as starting point - you post there initial
(starting) message and user messages only
- thread checks the queue and processes next message. If it is user
one - you get what you want (you can send it) and don't need to hold
lock on queue anymore.
If it is <start poll> message - it sends first poll message and saves
state in internal member.
- when message was sent and processed thread locks queue once again
and checks if there are any message requests. If yes - they are user
ones and must be sent. If not, queue can be unlocked and thread can
check state - should it send next poll message or not.

In this scenario you don't need to hold queue for long periods of
time. Scheme could be expanded with arbitrary number of message
sequences. It reminds me a bit job scheduler, don't you agree?

HTH
Alex

Charles Law said:
Hi Jon

You certainly appear to have grasped the nub of the problem. But I
am guilty of misleading in one respect.

When I said that the polling messages are all the same, I wasn't
quite telling the truth. They rotate round about 16 different
messages, so the first poll is type 1, the second type 2, and so on,
up to 16. Then they start again. The sequence is important, and
there must not be any omissions. So I do need to carefully
synchronise the polling with the acknowledgements, as well as the
intermittent UI messages.

I like the idea of using an event to get the next polling message
(rather like the TxBufferEmpty interrupt from a UART). I am also
looking at creating a dedicated queue class to maintain the
messages, rather than use the standard Queue class, in particular to
allow me to insert messages ahead of any polling messages (something
the standard class doesn't allow). For this reason, I am inheriting
from CollectionBase rather than Queue, unless you know of a better
one.

Charles
[By the way, thanks for your continued help]

I just need a continuous stream of polling messages to be sent out.
Each new message can be sent when the last one has been
acknowledged (by the remote end). However, the user can add a
non-polling message to the queue, in which case that is sent amid
the stream of polling messages.

In which case, the synchronization you need is between the polling
thread and the acknowledgement. You might want to do this with
events, for instance, firing an event whenever an acknowledgement
is received, and subscribing to that event with a delegate which
adds a message to the queue - possibly only if there isn't one
there already.
 
A

AlexS

I am not sure I see the reason for "blocking polling thread until the queue
is empty".
As I see it blocking (synchronization) is required only when you check queue
status - if it has anything in - and get request out.

HTH
Alex


Charles Law said:
Hi Alex

All the comments are useful and appreciated. I am trying to think of a way
for the queue object to block the polling thread until the queue is empty
when it tries to add a message, but allow messages from the UI thread to be
added to the queue immediately without blocking. If I can make it all
internal to the queue class then the queue can manage itself, rather than
rely on correct implementation in the external code where messages are added
and removed. The queue will also remove non-polling messages from the queue
first, when its DeQueue method is called, and then any remaining polling
messages.

Charles

Hi, Charles

couple (triple) of comments
- queue can serve as starting point - you post there initial
(starting) message and user messages only
- thread checks the queue and processes next message. If it is user
one - you get what you want (you can send it) and don't need to hold
lock on queue anymore.
If it is <start poll> message - it sends first poll message and saves
state in internal member.
- when message was sent and processed thread locks queue once again
and checks if there are any message requests. If yes - they are user
ones and must be sent. If not, queue can be unlocked and thread can
check state - should it send next poll message or not.

In this scenario you don't need to hold queue for long periods of
time. Scheme could be expanded with arbitrary number of message
sequences. It reminds me a bit job scheduler, don't you agree?

HTH
Alex

Charles Law said:
Hi Jon

You certainly appear to have grasped the nub of the problem. But I
am guilty of misleading in one respect.

When I said that the polling messages are all the same, I wasn't
quite telling the truth. They rotate round about 16 different
messages, so the first poll is type 1, the second type 2, and so on,
up to 16. Then they start again. The sequence is important, and
there must not be any omissions. So I do need to carefully
synchronise the polling with the acknowledgements, as well as the
intermittent UI messages.

I like the idea of using an event to get the next polling message
(rather like the TxBufferEmpty interrupt from a UART). I am also
looking at creating a dedicated queue class to maintain the
messages, rather than use the standard Queue class, in particular to
allow me to insert messages ahead of any polling messages (something
the standard class doesn't allow). For this reason, I am inheriting
from CollectionBase rather than Queue, unless you know of a better
one.

Charles
[By the way, thanks for your continued help]


Jon Skeet [C# MVP] wrote:
I just need a continuous stream of polling messages to be sent out.
Each new message can be sent when the last one has been
acknowledged (by the remote end). However, the user can add a
non-polling message to the queue, in which case that is sent amid
the stream of polling messages.

In which case, the synchronization you need is between the polling
thread and the acknowledgement. You might want to do this with
events, for instance, firing an event whenever an acknowledgement
is received, and subscribing to that event with a delegate which
adds a message to the queue - possibly only if there isn't one
there already.
 
C

Cor Ligthert

Hi Charles,

Did you already think on an extra thread, which handles the queues

And than only threads for handling the messages

Just thinking with you

Cor
 

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