Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Callbacks in VB.NET (windows service)

Status
Not open for further replies.

georgedumaine

Programmer
Sep 27, 2005
5
US
I am having a problem processing callback message in a windows service app. Bascially the program reads a text file with a list of video file names and plays them back via a dll that returns 2 messages I'm interested in. Here's what's going on and the relevant code:

If I put the line "Call mpgCallbackFunction(AddressOf CallBack)" in the OnStart routine I never get any messages back. So, I put the statement into the timer elapsed event. Note that the timer continues to fire but that it only actually does something the 1st time it fires. After that it just hangs around so my service doesn't die. I dispose of it in the OnStop routine. (Is this the best way to do this ... any other ideas?). Anyway, with this structure I get the 1st callback message and the app dies a horrible death. I think I have it structured wrong and I think it has to do with where I put "Call mpgCallbackFunction(AddressOf CallBack)". I have also tried putting it in the InitCard() routine but that doesn't seem to help. Anything help would be greatly appreciated.


Delegate Sub CallBackDelegate(ByVal CardNum As Integer, ByVal ChanNum As Integer, ByVal Message As Short)
Declare Sub mpgCallbackFunction Lib "SomePlayback.dll" (ByVal ptrFunction As CallBackDelegate)
'declare callback function

Protected Overrides Sub OnStart(ByVal args() As String)
gLogFile = "C:\MyService.log"
gPlaylist = "C:\MyService.mpl"
gStopService = False
gStartService = True
Timer1.Enabled = True
End Sub

Private Sub Timer1_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed
If gStartService And Not gStopService Then
WriteToLog(0, 0, "***********************************************")
WriteToLog(5, 0, "Service Started.")
play_fNum = FreeFile()
FileOpen(play_fNum, gPlaylist, OpenMode.Input, OpenAccess.Read, OpenShare.Shared)
Call WriteToLog(0, 0, "Opened: " & gPlaylist)

Call Init_Card()
Call mpgCallbackFunction(AddressOf CallBack)

'This loads the first file and plays it, then the call back queue's subsequent files
gStartService = False 'because it's already started now so don't do this again.

Dim mFileToPlay As String = ""
Dim mImgFile As String

Call GetNextPLEntry(mPl)
If mPl.ContentID > 0 Then
mFileToPlay = GetCatalogEntry(mPl.ContentID)
mImgFile = GetCatalogEntry(mPl.ImageID)
Call DecPlay(mFileToPlay, mPl)
End If
End If

End Sub

Public Sub CallBack(ByVal CardNum As Integer, ByVal ChanNum As Integer, ByVal Message As Short)
'handle the messages
Select Case Message
Case MPG_FILE_PLAY_COMPLETE
WriteToLog(0, 0, "MPG_FILE_PLAY_COMPLETE")
gMPG_FILE_PLAY_COMPLETE = True

Case MPG_FILE_READ_START
WriteToLog(0, 0, "MPG_FILE_READ_START")
Call GetNextPLEntry(mPl)
If mPl.ContentID > 0 Then
Call WriteToLog(0, 0, "About to queue: " & GetCatalogEntry(mPl.ContentID))
Call mpgLoadNext(gCard, gZone, GetCatalogEntry(mPl.ContentID))
'mImgFile = GetCatalogEntry(mPl.ImageID)
Else
'We are done with the playlist
Call WriteToLog(0, 0, "Done with the playlist")
Call mpgStop(gCard, gZone)
Call mpgCloseDriver()
End If

Case Else
WriteToLog(0, 0, "Received message with value of " & Message)
End Select
End Sub

 
I think the only thing you can use for a parameter on a callback function is IAsynchResult. You'll have to move the parameters to private module variables and set them before the callback is called.

-Rick

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
What do you think about the structure of the service in general? Ie: Is it OK to have a timer that doesn't really do anything but hang out and have all the real work being done in the call back function? I just don't have much experience with delegates and callbacks in a service (console) applicaiton so I'm not sure the structure is correct.

I'm also not sure about variable scoping (or the scoping of the callback function) in this structure. Like I mentioned, if I call the callback in the OnStart routine - it never fires! The timer elapsed event is declared as private so may the callback should be put somewhere else? Where?

The DLL I'm using returns 3 parameters - are you suggesting that I declare them all as IAsynchResult?

I'll have to look at the link you sent a little longer. At first glance I'm not following how those call backs relate to the "long process".

Thanks for your help and I really appreciate your prompt response! George

 
Using a timer/thread to run your process in a service is fine. I'm not sure if you need to keep the timer going after you set up the call back though.

Just did a quick bit of searching and realised my understanding was a bit flawed. Looks like IAsynchResults does not hold the return values as I had originally though, it just holds the state of the thread. But you can use it to determine when a thread has completed and call the .EndInvoke method which works with parameters. If I get a chance, I'll dig into this. It's end of fiscal year here though, so I'm a bit swamped. But this sounds like a fun threading issue.

What library are you referencing? and would you be willing to share the full code?

-Rick


As for the Iasynchresults, all of your values should be contained with in it. I haven't had to work with it much, none of my current threading code worries about return values. I can try to google something up, but if my understanding is correct, what ever those return values are will be wrapped up in the IAsynchResults object.

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
You pretty much need to use a timer or a worker thread in a service. If you put your main code in the OnStart event, you're actually running on the ServiceControlManager's thread, and he'll kill you (call OnStop, etc) if you don't return in a timely manner.

Chip H.


____________________________________________________________________
Donate to Katrina relief:
If you want to get the best response to a question, please read FAQ222-2244 first
 
That's what I've found out, you are absolutely right. If I do any processing at all in the OnStart routine the service manager times it out and fires the OnStop routine almost before I can blink. The timer method I described seems to be working best but I'm getting erratic results with the callback delegates. I have come across some articles and postings that suggest their is a problem with the way .NET 2003 handles callbacks so... I've shelved that approach for now and am moving forward on another path that is callbackless. It won't be long until I can test it with .NET 2005 and I'm hoping it will work like magic.

Thanks again for your help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top