VB.NET: RasDial + CallBacks + throwing events = frozen UI?

B

bhc

all-

up until just recently, i was fairly sure i'd implemented a RasDial
class in VB.NET complete with a callback to get updated status. from
this wrapper, when i throw an event back to the calling program, i can
console.writeline the state successfully. but as soon as i replace
that line with updating the UI, the program freezes, and execution
halts. no exceptions are thrown or anything (i've got the line in a
try...catch block, but nothing happens), the app just freezes. in
fact, if i just mouseover the line that causes the problem (in this
case, it's just a simple Me.Text of a form that's calling my object),
the program freezes. what's amusing is that i can successfully
observe and return Me.Left...i imagine it has something to do with the
RasDial occurring in a separate thread...but it's not working
regardless.

any help would be appreciated, thanks in advance.

relevant sample code:
---
'in a class
'The callback function for obtaining updated ras states
Private mRasCallBack As RasDialCallBack = AddressOf RasDialFunc

Public Function Dial(ByVal Parameters As RASDIALPARAMS) As IntPtr
Try
'Declare return value
Dim lReturn As Int32

'Declare handle for RAS dial attempt
Dim lHandle As IntPtr

'Reset flag that controls whether or not we're done dialing
mRasDone = False

'Start dialing
lReturn = modRASAPI.RasDial(IntPtr.Zero, Nothing,
Parameters, 0, mRasCallBack, lHandle)

'See if an error occurred
If lReturn <> 0 Then
'Get the error message
Dim lErrString As String =
modRASAPI.DecodeRASErrorNumber(lReturn)

'Throw the error
Throw New Exception(lErrString)
End If

'Return the handle
Dial = lHandle
Catch ex As Exception
Throw ex
End Try
End Function

Private Function RasDialFunc(ByVal unMsg As Integer, ByVal
rasconnstate As Integer, ByVal dwError As Integer) As Integer
Try
'Get the new state
Dim lState As RasConnState = rasconnstate

'Throw a state changed event
RaiseEvent StateChanged(lState, GetConStateSTR(lState))

'See if we're either connected or disconnected
Select Case lState
Case modRASEnums.RasConnState.Connected
'Raise a done message
ThrowDoneEvent(True, 0, "")

Case modRASEnums.RasConnState.Disconnected
'Raise a done message
ThrowDoneEvent(True, 0, "")
End Select

'See if an error occurred
If dwError <> 0 Then
'First we need to determine what the error is
Dim lErrorMessage As String
Try
'Attempt to decode the error number
lErrorMessage =
modRASAPI.DecodeRASErrorNumber(dwError)
Catch ex As Exception
'Assume the error message, if there was one
lErrorMessage = ex.Message
End Try

'Raise a done message
ThrowDoneEvent(False, dwError, lErrorMessage)
End If

Catch ex As Exception
Throw ex
End Try
End Function
---
'in the calling program

Private Sub mRAS_StateChanged(ByVal CurrentState As
pdsRAS.modRASEnums.RasConnState, ByVal CurrentStateStr As String)
Handles mRAS.StateChanged
Try
'this line works, and i can see the updated state in the
console
Console.WriteLine(CurrentState)
'this line does not work, and the app halts
Me.Text = CurrentState
Catch ex As Exception
Stop
End Try
End Sub
 
T

Tom Shelton

bhc said:
all-

up until just recently, i was fairly sure i'd implemented a RasDial
class in VB.NET complete with a callback to get updated status. from
this wrapper, when i throw an event back to the calling program, i can
console.writeline the state successfully. but as soon as i replace
that line with updating the UI, the program freezes, and execution
halts. no exceptions are thrown or anything (i've got the line in a
try...catch block, but nothing happens), the app just freezes. in
fact, if i just mouseover the line that causes the problem (in this
case, it's just a simple Me.Text of a form that's calling my object),
the program freezes. what's amusing is that i can successfully
observe and return Me.Left...i imagine it has something to do with the
RasDial occurring in a separate thread...but it's not working
regardless.

More then likely you are right - it is occuring on a separate thread.
You should check the Me.InvokeRequired propertie in the callback - if
it is true, then you need to call Me.Invoke so that the call is
marshaled to the UI thread...
 
B

bhc

that's what i was afraid of...perhaps you could expand a little bit on
Invoking, as it's definitely not me strong suit...

what i gather, is that i need to have a Sub that updates the form text,
declare a Delegate that has the same signature, and a variable of the
Delegate type that has an AddressOf pointing to the Sub. what i have
right now....

Private Delegate Sub DelUpdateTextCallBack(ByVal NewText As String)
Private x As DelUpdateTextCallBack = AddressOf UpdateText

Private Sub UpdateText(ByVal NewText As String)
Me.Text = NewText
Application.DoEvents()
End Sub

then in the mRAS_StateChanged above...

If Me.InvokeRequired Then
Me.Invoke(x, New Object() {CurrentState})
End If

i imagine it's not right, as i'm experiencing the same problems already
on the Me.Invoke line, but that was the best i could come up with...
 
T

Tom Shelton

bhc said:
that's what i was afraid of...perhaps you could expand a little bit on
Invoking, as it's definitely not me strong suit...

what i gather, is that i need to have a Sub that updates the form text,
declare a Delegate that has the same signature, and a variable of the
Delegate type that has an AddressOf pointing to the Sub. what i have
right now....

Private Delegate Sub DelUpdateTextCallBack(ByVal NewText As String)
Private x As DelUpdateTextCallBack = AddressOf UpdateText

Private Sub UpdateText(ByVal NewText As String)
Me.Text = NewText
Application.DoEvents()
End Sub

then in the mRAS_StateChanged above...

If Me.InvokeRequired Then
Me.Invoke(x, New Object() {CurrentState})
End If

i imagine it's not right, as i'm experiencing the same problems already
on the Me.Invoke line, but that was the best i could come up with...

bhc - did you ever get this sorted out? I've been sort of out for the
last couple of days... I got your email, and I came back here to check
if any other answers were offered - apparently not. I can try and do a
little bit of playing with this at home tonight, if you still need the
help....
 
B

bhc

hi tom - thanks for getting back to me.

turns out this was my fault - although it still doesn't make much sense
to me. here's the deal...in the calling thread, i started dialing,
then entered a loop where i slept 100 miliseconds at a time. when the
event came bubbling up from the RasCallBack, any screen update would
cause the program to freeze. well...all i have to do was throw in a
DoEvents, and it worked. i imagine the screen wasn't able to update
for whatever reason, and the DoEvents was needed to flush out the
request. just a guess - like i said, i really don't understand why it
didn't work to begin with...
 

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