By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,068 Members | 1,210 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,068 IT Pros & Developers. It's quick & easy.

Alternatives to Application.DoEvents?

P: n/a
I have an application where I would like to block waiting on an asynchronous
event and still process messages. I can implement a hard loop to block such
as:

Do While StillWaiting
Application.DoEvents
Loop

In this case the asynchronous thread can just set StillWaiting=False when
complete.

But this hard loop is CPU intensive. Using VB6 I solved this problem by
making my own windows message loop using WIN32 calls such as:

Do While (GetMessage(Message, 0, 0, 0) <> 0)
TranslateMessage(Message)
DispatchMessageA(Message)

If Not StillWaiting Then
Exit Do
End If
Loop

In this case the async thread needs to set StillWaiting=False and send a
message to the application message queue to wake it up.

My question is will this approach work under .NET? I've tried it and it
seems to but I am concerned about how the WIN32 calls work and/or other
issues I may be missing out on...
Nov 21 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Hi,

http://msdn.microsoft.com/msdnmag/is...asicInstincts/

Ken
---------------
"TrtnJohn" <Tr******@discussions.microsoft.com> wrote in message
news:9C**********************************@microsof t.com...
I have an application where I would like to block waiting on an asynchronous
event and still process messages. I can implement a hard loop to block such
as:

Do While StillWaiting
Application.DoEvents
Loop

In this case the asynchronous thread can just set StillWaiting=False when
complete.

But this hard loop is CPU intensive. Using VB6 I solved this problem by
making my own windows message loop using WIN32 calls such as:

Do While (GetMessage(Message, 0, 0, 0) <> 0)
TranslateMessage(Message)
DispatchMessageA(Message)

If Not StillWaiting Then
Exit Do
End If
Loop

In this case the async thread needs to set StillWaiting=False and send a
message to the application message queue to wake it up.

My question is will this approach work under .NET? I've tried it and it
seems to but I am concerned about how the WIN32 calls work and/or other
issues I may be missing out on...

Nov 21 '05 #2

P: n/a
I am not sure that asynchronous methods will give me the behavior I am
looking for. I want the original call to NOT return to the caller until the
async method completes. While the original call is blocked I want windows
messages to still be processed. Unless I am misunderstaning things, I would
still have to poll the status of the async method in order to block waiting
for it to complete. I may as well use DoEvents in that case. Here's a few
more details about the problem:

The application I am working talks to a serial device. The main thread
sends requests and the secondary thread reads responses. Once a request is
sent I want to block until a response is received or timeout occurs. During
this wait time I do not want the UI to go unresponsive. Basically, I am
trying to hide the fact that commands to this device requires a
request/response and wrap them into a single synchronous method call for
higher level objects to use.

"Ken Tucker [MVP]" wrote:
Hi,

http://msdn.microsoft.com/msdnmag/is...asicInstincts/

Ken
---------------
"TrtnJohn" <Tr******@discussions.microsoft.com> wrote in message
news:9C**********************************@microsof t.com...
I have an application where I would like to block waiting on an asynchronous
event and still process messages. I can implement a hard loop to block such
as:

Do While StillWaiting
Application.DoEvents
Loop

In this case the asynchronous thread can just set StillWaiting=False when
complete.

But this hard loop is CPU intensive. Using VB6 I solved this problem by
making my own windows message loop using WIN32 calls such as:

Do While (GetMessage(Message, 0, 0, 0) <> 0)
TranslateMessage(Message)
DispatchMessageA(Message)

If Not StillWaiting Then
Exit Do
End If
Loop

In this case the async thread needs to set StillWaiting=False and send a
message to the application message queue to wake it up.

My question is will this approach work under .NET? I've tried it and it
seems to but I am concerned about how the WIN32 calls work and/or other
issues I may be missing out on...

Nov 21 '05 #3

P: n/a
On 2005-07-30, TrtnJohn <Tr******@discussions.microsoft.com> wrote:
I am not sure that asynchronous methods will give me the behavior I am
looking for. I want the original call to NOT return to the caller until the
async method completes. While the original call is blocked I want windows
messages to still be processed. Unless I am misunderstaning things, I would
still have to poll the status of the async method in order to block waiting
for it to complete. I may as well use DoEvents in that case. Here's a few
more details about the problem:

No... An async method can call a callback when it is completed. You can
pass the callback to the BeginInvoke method of the delegate. In other
words, you don't really need to do a separate thread (well, not
explicitly - async methods are called on a separate thread).

The application I am working talks to a serial device. The main thread
sends requests and the secondary thread reads responses. Once a request is
sent I want to block until a response is received or timeout occurs. During
this wait time I do not want the UI to go unresponsive. Basically, I am
trying to hide the fact that commands to this device requires a
request/response and wrap them into a single synchronous method call for
higher level objects to use.


I wouldn't do it that way... I would expose this as events. Something
like a commandcomplete event. Then the main thread calls the method and
returns - there for remains responsive - though, you might have to lock
the user out of certain gui functions until the work is done. The class
wraps the thread and the async delegate calls, and when it gets it's result,
raises an event back to the main form.

Make sense?
--
Tom Shelton [MVP]
Nov 21 '05 #4

P: n/a
Tom,

That makes good sense. But, let me explain why I have problems with that
approach and why I am trying to keep the methods synchronous. There are
actually many different types of commands to the device with many different
functions, parameters and return data. I want to hide all that and just let
the application perform simple requests. Each application request may
execute many different commands to the device. The command sequence and
logic is controlled by a number of factors. These include: The initial
application request, parameters from the initial application request, and the
return data from each individual command. If I make a CommandResponse event
I'll need to keep a ton of globals to manage the state of each request. If I
make the commands synchronous I can implement each application request using
flow control within the method instead of relying on global state variables.
For example:

Public Sub AppRequest1(Byval Param as String)
If Device.Command1 = Success Then
CurStatus = Device.Command2(Param)
Return Device.Command3(CurStatus)
Else
Device.Command4(Param)
End If
End Sub

As you see, if I used events for every command completion and tried to
implement similar logic as the sample above would require a lot of global
state variables. And, the problem grows exponentially depending on how many
different application requests and commands I have.

"Tom Shelton" wrote:
On 2005-07-30, TrtnJohn <Tr******@discussions.microsoft.com> wrote:
I am not sure that asynchronous methods will give me the behavior I am
looking for. I want the original call to NOT return to the caller until the
async method completes. While the original call is blocked I want windows
messages to still be processed. Unless I am misunderstaning things, I would
still have to poll the status of the async method in order to block waiting
for it to complete. I may as well use DoEvents in that case. Here's a few
more details about the problem:


No... An async method can call a callback when it is completed. You can
pass the callback to the BeginInvoke method of the delegate. In other
words, you don't really need to do a separate thread (well, not
explicitly - async methods are called on a separate thread).

The application I am working talks to a serial device. The main thread
sends requests and the secondary thread reads responses. Once a request is
sent I want to block until a response is received or timeout occurs. During
this wait time I do not want the UI to go unresponsive. Basically, I am
trying to hide the fact that commands to this device requires a
request/response and wrap them into a single synchronous method call for
higher level objects to use.


I wouldn't do it that way... I would expose this as events. Something
like a commandcomplete event. Then the main thread calls the method and
returns - there for remains responsive - though, you might have to lock
the user out of certain gui functions until the work is done. The class
wraps the thread and the async delegate calls, and when it gets it's result,
raises an event back to the main form.

Make sense?
--
Tom Shelton [MVP]

Nov 21 '05 #5

P: n/a
Hi John

You seem to be describing exactly a situation I had to code for a little
while ago. The solution I went for was to use the Monitor class.

The logic is this:

Send command to remote serial device on main thread.
Call function WaitForReply to block main thread until response received or
time-out.

WaitForReply is coded thus:

<code>
Private m_ResponseReceived As Object = New Object

Private Function WaitReply(ByVal timeout As Integer) As Boolean

SyncLock m_ResponseReceived
If Monitor.Wait(m_ResponseReceived, timeout) Then
Return True
Else
Return False
End If
End SyncLock

End Function
</code>

Now, there is an event that is raised when serial data is received. In this
event, I check what has been received and when I have a complete reply, I
call ResponseReceived, below.

<code>
Private Sub ResponseReceived()

SyncLock m_ResponseReceived
' Pulse this object, which any waiting thread will be attempting
' to get a lock on.
Monitor.Pulse(m_ResponseReceived)
End SyncLock

End Sub
</code>

That's it. The main thread is blocked until a response is received or there
is a time-out. The cpu does not go off the scale, and everything is nice and
responsive so long as the value of timeout is quite small.

HTH

Charles
"TrtnJohn" <Tr******@discussions.microsoft.com> wrote in message
news:AA**********************************@microsof t.com...
Tom,

That makes good sense. But, let me explain why I have problems with that
approach and why I am trying to keep the methods synchronous. There are
actually many different types of commands to the device with many
different
functions, parameters and return data. I want to hide all that and just
let
the application perform simple requests. Each application request may
execute many different commands to the device. The command sequence and
logic is controlled by a number of factors. These include: The initial
application request, parameters from the initial application request, and
the
return data from each individual command. If I make a CommandResponse
event
I'll need to keep a ton of globals to manage the state of each request.
If I
make the commands synchronous I can implement each application request
using
flow control within the method instead of relying on global state
variables.
For example:

Public Sub AppRequest1(Byval Param as String)
If Device.Command1 = Success Then
CurStatus = Device.Command2(Param)
Return Device.Command3(CurStatus)
Else
Device.Command4(Param)
End If
End Sub

As you see, if I used events for every command completion and tried to
implement similar logic as the sample above would require a lot of global
state variables. And, the problem grows exponentially depending on how
many
different application requests and commands I have.

"Tom Shelton" wrote:
On 2005-07-30, TrtnJohn <Tr******@discussions.microsoft.com> wrote:
> I am not sure that asynchronous methods will give me the behavior I am
> looking for. I want the original call to NOT return to the caller
> until the
> async method completes. While the original call is blocked I want
> windows
> messages to still be processed. Unless I am misunderstaning things, I
> would
> still have to poll the status of the async method in order to block
> waiting
> for it to complete. I may as well use DoEvents in that case. Here's a
> few
> more details about the problem:
>


No... An async method can call a callback when it is completed. You can
pass the callback to the BeginInvoke method of the delegate. In other
words, you don't really need to do a separate thread (well, not
explicitly - async methods are called on a separate thread).

> The application I am working talks to a serial device. The main thread
> sends requests and the secondary thread reads responses. Once a
> request is
> sent I want to block until a response is received or timeout occurs.
> During
> this wait time I do not want the UI to go unresponsive. Basically, I
> am
> trying to hide the fact that commands to this device requires a
> request/response and wrap them into a single synchronous method call
> for
> higher level objects to use.


I wouldn't do it that way... I would expose this as events. Something
like a commandcomplete event. Then the main thread calls the method and
returns - there for remains responsive - though, you might have to lock
the user out of certain gui functions until the work is done. The class
wraps the thread and the async delegate calls, and when it gets it's
result,
raises an event back to the main form.

Make sense?
--
Tom Shelton [MVP]

Nov 21 '05 #6

P: n/a
Thanks Charles. Sorry it took me so long to get back to your reply. Your
solution works well if the reply is received immediately. In my case, it
could take the device many seconds to reply. Your WaitReply method would be
blocked during this timeframe but the UI would be unresponsive while the
blocking goes on. (Something I am trying to avoid). I could do something
like:

Do While StillNoReply
WaitReply(short_timeout)
Application.DoEvents
Loop

But, this still seems a little clunky. Surprisingly, my original design
seems to work exactly how I wanted. (See first post using the GetMessage to
block). But, I am worried because I am going outside of the .NET framework.

"Charles Law" wrote:
Hi John

You seem to be describing exactly a situation I had to code for a little
while ago. The solution I went for was to use the Monitor class.

The logic is this:

Send command to remote serial device on main thread.
Call function WaitForReply to block main thread until response received or
time-out.

WaitForReply is coded thus:

<code>
Private m_ResponseReceived As Object = New Object

Private Function WaitReply(ByVal timeout As Integer) As Boolean

SyncLock m_ResponseReceived
If Monitor.Wait(m_ResponseReceived, timeout) Then
Return True
Else
Return False
End If
End SyncLock

End Function
</code>

Now, there is an event that is raised when serial data is received. In this
event, I check what has been received and when I have a complete reply, I
call ResponseReceived, below.

<code>
Private Sub ResponseReceived()

SyncLock m_ResponseReceived
' Pulse this object, which any waiting thread will be attempting
' to get a lock on.
Monitor.Pulse(m_ResponseReceived)
End SyncLock

End Sub
</code>

That's it. The main thread is blocked until a response is received or there
is a time-out. The cpu does not go off the scale, and everything is nice and
responsive so long as the value of timeout is quite small.

HTH

Charles
"TrtnJohn" <Tr******@discussions.microsoft.com> wrote in message
news:AA**********************************@microsof t.com...
Tom,

That makes good sense. But, let me explain why I have problems with that
approach and why I am trying to keep the methods synchronous. There are
actually many different types of commands to the device with many
different
functions, parameters and return data. I want to hide all that and just
let
the application perform simple requests. Each application request may
execute many different commands to the device. The command sequence and
logic is controlled by a number of factors. These include: The initial
application request, parameters from the initial application request, and
the
return data from each individual command. If I make a CommandResponse
event
I'll need to keep a ton of globals to manage the state of each request.
If I
make the commands synchronous I can implement each application request
using
flow control within the method instead of relying on global state
variables.
For example:

Public Sub AppRequest1(Byval Param as String)
If Device.Command1 = Success Then
CurStatus = Device.Command2(Param)
Return Device.Command3(CurStatus)
Else
Device.Command4(Param)
End If
End Sub

As you see, if I used events for every command completion and tried to
implement similar logic as the sample above would require a lot of global
state variables. And, the problem grows exponentially depending on how
many
different application requests and commands I have.

"Tom Shelton" wrote:
On 2005-07-30, TrtnJohn <Tr******@discussions.microsoft.com> wrote:
> I am not sure that asynchronous methods will give me the behavior I am
> looking for. I want the original call to NOT return to the caller
> until the
> async method completes. While the original call is blocked I want
> windows
> messages to still be processed. Unless I am misunderstaning things, I
> would
> still have to poll the status of the async method in order to block
> waiting
> for it to complete. I may as well use DoEvents in that case. Here's a
> few
> more details about the problem:
>

No... An async method can call a callback when it is completed. You can
pass the callback to the BeginInvoke method of the delegate. In other
words, you don't really need to do a separate thread (well, not
explicitly - async methods are called on a separate thread).
> The application I am working talks to a serial device. The main thread
> sends requests and the secondary thread reads responses. Once a
> request is
> sent I want to block until a response is received or timeout occurs.
> During
> this wait time I do not want the UI to go unresponsive. Basically, I
> am
> trying to hide the fact that commands to this device requires a
> request/response and wrap them into a single synchronous method call
> for
> higher level objects to use.

I wouldn't do it that way... I would expose this as events. Something
like a commandcomplete event. Then the main thread calls the method and
returns - there for remains responsive - though, you might have to lock
the user out of certain gui functions until the work is done. The class
wraps the thread and the async delegate calls, and when it gets it's
result,
raises an event back to the main form.

Make sense?
--
Tom Shelton [MVP]


Nov 21 '05 #7

P: n/a
"TrtnJohn" <Tr******@discussions.microsoft.com> schrieb
Thanks Charles. Sorry it took me so long to get back to your reply.
Your solution works well if the reply is received immediately. In
my case, it could take the device many seconds to reply. Your
WaitReply method would be blocked during this timeframe but the UI
would be unresponsive while the blocking goes on. (Something I am
trying to avoid). I could do something like:

Do While StillNoReply
WaitReply(short_timeout)
Application.DoEvents
Loop

But, this still seems a little clunky. Surprisingly, my original
design seems to work exactly how I wanted. (See first post using
the GetMessage to block). But, I am worried because I am going
outside of the .NET framework.

What about a little Threading.thread.sleep(50) in the loop? Would reduce CPU
usage. I assume you want to go the DoEvents way, thus I don't suggest
anything else because it's already been done earlier in this thread.
Armin

Nov 21 '05 #8

P: n/a
Thanks Armin. That actually sounds safe and simple. I'll give that a try.

"Armin Zingler" wrote:
"TrtnJohn" <Tr******@discussions.microsoft.com> schrieb
Thanks Charles. Sorry it took me so long to get back to your reply.
Your solution works well if the reply is received immediately. In
my case, it could take the device many seconds to reply. Your
WaitReply method would be blocked during this timeframe but the UI
would be unresponsive while the blocking goes on. (Something I am
trying to avoid). I could do something like:

Do While StillNoReply
WaitReply(short_timeout)
Application.DoEvents
Loop

But, this still seems a little clunky. Surprisingly, my original
design seems to work exactly how I wanted. (See first post using
the GetMessage to block). But, I am worried because I am going
outside of the .NET framework.

What about a little Threading.thread.sleep(50) in the loop? Would reduce CPU
usage. I assume you want to go the DoEvents way, thus I don't suggest
anything else because it's already been done earlier in this thread.
Armin

Nov 21 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.