Re: Alternatives to Application.DoEvents?



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" <TrtnJohn@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
> news:AADBF45C-483B-4880-91B6-624F7B1E3D83@xxxxxxxxxxxxxxxx
> > 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 <TrtnJohn@xxxxxxxxxxxxxxxxxxxxxxxxx> 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]
> >>
>
>
>
.



Relevant Pages


Quantcast