Click here to Skip to main content
15,886,016 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a timer which calls a function to send an asynchronous query to a controller and I need the result passed back to the timer.

Here's an abbreviated version of what's going on.

Public Sub Timer2_Tick(ByVal sender As Object, ByVal e As EventArgs)

Dim remainingTime As TimeSpan = Me.alarmTime.Subtract(Date.Now)

If remainingTime.Seconds Mod 10 = 0 Then 'this will be true every ten seconds

strResponse = controllerAsyncDownload(IPAddress, "200") 'check Lamp Status

If Instr(strResponse, "0") Then
'change the status of the projector on the GUI
End If

End If
End Sub

Public Function controllerAsyncDownload(IPAddress As Uri, amxCase As String) As String

AddHandler client.DownloadStringCompleted, AddressOf ListDownloaded

Dim ipAddressComp As New Uri(IPAddress.ToString & amxCase)
Try
client.DownloadStringAsync(ipAddressComp, amxCase)
Catch ex As Exception
MsgBox(ex.Message)
End Try

End Function

Public Function ListDownloaded(ByVal sender As Object, ByVal e As Net.DownloadStringCompletedEventArgs) As String

If e.Cancelled = False AndAlso e.Error Is Nothing Then
strResponse = e.Result.ToString
End If
ListDownloaded = strResponse
End Function

My question is: How do I get the response captured in ListDownloaded back to the Timer Sub?
Update: It may well be that this is the way MS intends 'Handlers' to be used. I can of course place the 'action' code in the Handler... and am going to do so. I'd prefer to keep my code in clearly defined sections; In this case maybe I have to let some sections fall down the page.
Posted
Updated 22-Jul-13 5:31am
v4

Few things...

First, please use the formatting tools when you post code. It makes it much more readable and helps those of us with old eyes like mine.

Second, you have some fundamental architectural issues. You should probably move your download/status code to its own static class (module in VB land). In the constructor of that module, create your client and add your handler. The way you have it now, you add a handler each time you call out to check the status. That will work for about the first 500 or so calls then it will crash your app because you've never removed the handlers. You'll have this terribly long eventing list holding all kinds of useless objects in memory. If you move it all to a module and only add the handler ONCE then you are in much better shape.

Further, you can add the response as a public variable on that module. Then you can set it in the event callback and read it in the timer. However, you have to take into consideration threading limitations.

The timer's tick event happens on its own thread... not the UI thread... The callback delegate will also happen on it's own thread. Both of these are really important to know because it means that the response needs tucked into a variable in your module that is protected by a semaphore or a lock object or something else to prevent it getting changed in a thread-unsafe-crash-your-app-at-random-times type of situation.

Further, because the timer tick takes place on a separate thread, you can't directly update your UI from within the tick event. You have some choices here... You could marshal the call over to the UI thread from the tick event setting your UI element based on the response object. There are lots of samples on how to update UI elements from non-UI threads so I won't go into detail.

- OR -

Since you need to wrap the setting and getting of the response string in a thread-safe manner, you could go ahead and raise an event in the setter method. This would be analogous to raising INotifyPropertyChange in MVVM. The gist is that if the response string changes, you would raise an event. Since the event is defined in the static module, the code for your UI could hook the event and handle the change directly... without ever using the timer. Again, however, you would have to marshal the call to the UI thread using Invoke because the event would be raised on the callback's thread... not the UI thread. If you follow that method, the timer could be extended to only fire when you need to actually make the check. In the tick event, you fire off the check. In the callback handler for the check, you set the response string. The response string, if it is different, raises an event that the UI is watching for. It marshals the call over to the UI thread via Invoke and boom goes the dynamite... a UI that updates with your projector status.
 
Share this answer
 
Comments
kcjames 19-Jul-13 16:41pm    
Thanks Jason. This information will be most valuable. Much appreciated.
use jquery framework, it can help you
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900