Not Responding

ggunter

Well-known member
Joined
Apr 23, 2008
Messages
137
Programming Experience
Beginner
Hope this is in the correct place.

I have a form containing one 3rd party control and one button. When the button is clicked, it calls a class containing a function which acts on the 3rd party control.

My problem is that when I run the program, it hangs after just a few seconds and the form's caption changes from "Form 1" to "Form 1 (Not Responding)".

The company I work for has been using this control for more than a decade and I can't find any documentation on it anywhere. In addition, the program doesn't throw any errors that I have been able to find it just hangs.

Any ideas would be GREATLY appreciated.
 
If you're saying it is a control, you cannot have it run in another thread, so I can only suggest to click the "break all" button in VS and see where it stops. You may find that some events are thrown too many times and just keep repeating themselves. Or maybe you loop through something until the value is right and it never is.

All I can suggest is to run it in the debugger and see which loop is actually blocking the flow of the application until I can actually look at some code...
 
Thank you for your quick reply, Stonkie. I apologize for not being able to repond sooner.

Main form button click event:
Private Sub btnLogon_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLogon.Click
'initialize object
Dim ggRum As New ggBaseRumba
'user indicator
Me.Cursor = Cursors.WaitCursor
'connect to rumba
ggRum.Connection(Me.axRumba) ***axRumba = third party control***
'check for tors screen
If ggRum.WaitForScreen(Me.axRumba, "You are authorized", 6) = 0 Then
'transmit tors
ggRum.Torrs("collnh", Me.axRumba)
Else
GoTo ExitHere
End If

****The code, up to this point, functions perfectly. Once I enter the next section of code, the form and control become unresponsive. If I delete the section below, it goes back to working again.****

If ggRum.WaitForScreen(Me.axRumba, "Type userid", 7) = 0 Then
'enter user id and password
ggRum.Acid(Me.axRumba, "AcidHere", "PasswordHere")
Else
GoTo ExitHere
End If
ExitHere:
'user indicator
Me.Cursor = Cursors.Default
End Sub


ggBaseRumba class:

Imports System
Imports System.Diagnostics

Public Class ggBaseRumba
'Declare Key Constants
Public Const ENTERKEY As String = "@E"

Public Sub Acid(ByRef mRumba As AxObjectXMFDisplay.AxObjectXMFDisplay, ByVal strAcid As String, ByVal strPass As String)
mRumba.PutScreen2(strAcid, 7, 24)
mRumba.PutScreen2(strPass, 8, 24)
mRumba.SendKeys(ENTERKEY)
End Sub

Public Function Connection(ByRef mRumba As AxObjectXMFDisplay.AxObjectXMFDisplay) As Boolean
'declare object
Dim connWatch As Stopwatch
'initialize return value
Connection = True
'check for connection
If mRumba.HostConnected = False Then
'start timer
connWatch.Start()
'wait for connection
While mRumba.HostConnected = False
'check for 60 sec timeout
connWatch.Stop()
If connWatch.ElapsedMilliseconds >= 60000 Then
'reset return value
Connection = False
Exit While
End If
'restart timer
connWatch.Start()
End While
End If
'terminate object
connWatch = Nothing
End Function

Public Sub Torrs(ByVal strTors As String, ByRef mRumba As AxObjectXMFDisplay.AxObjectXMFDisplay)
'enter tors
mRumba.PutScreen2(strTors, 15, 2)
'transmit enter key
mRumba.SendKeys(ENTERKEY)
End Sub

Public Function WaitForScreen(ByRef mRumba As AxObjectXMFDisplay.AxObjectXMFDisplay, ByVal Text As String, ByVal Row As Integer) As Integer
'initialize
Dim waitWatch As New Stopwatch
Dim strTemp As String
'capture existing text at indicated line
strTemp = mRumba.GetScreen2(Row, 1, 80)
'check for text
While InStr(strTemp, Text, CompareMethod.Text) = 0
'begin timer
waitWatch.Start()
'capture text
strTemp = mRumba.GetScreen2(Row, 1, 80)
'check for 60 sec timeout
waitWatch.Stop()
If waitWatch.ElapsedMilliseconds >= 60000 Then
WaitForScreen = 4
Exit While
End If
End While
'terminate object
waitWatch = Nothing
End Function
End Class

Am I overlooking something basic??
 
Sorry about the formatting above.

I have narrowed it down to the following piece of code.

VB.NET:
Public Function WaitForScreen(ByRef mRumba As AxObjectXMFDisplay.AxObjectXMFDisplay, ByVal Text As String, ByVal Row As Integer) As Integer
      'initialize
      Dim waitWatch As New Stopwatch
      Dim strTemp As String
      'capture existing text at indicated line
      strTemp = mRumba.GetScreen2(Row, 1, 80)
      'check for text
      While InStr(strTemp, Text, CompareMethod.Text) = 0
         'begin timer
         waitWatch.Start()
         'capture text
         strTemp = mRumba.GetScreen2(Row, 1, 80)
         'check for 60 sec timeout
         waitWatch.Stop()
         If waitWatch.ElapsedMilliseconds >= 60000 Then
            WaitForScreen = 4
            Exit While
         End If
      End While
      'terminate object
      waitWatch = Nothing
   End Function


I'm sure I'm going to feel like an idiot but what am I missing?:confused:
 
If this line :

VB.NET:
strTemp = mRumba.GetScreen2(Row, 1, 80)

Ever takes infinte time in any situation, even if you detect it took more than 60 seconds after it finishes, it will still take as much time as it needs. So if this call can ever take an infinite amount of time, the method will block there.

Try to add this line as the first statement of the loop to see at which iteration it stops. If it never prints anything to the console, it's the first call to mRumba.GetScreen2 that blocks. If it prints stuff indefinitly, the loop condition is bad.

VB.NET:
Console.print(strTemp)

What you seem to be wanting is to call the mRumba.GetScreen2 method until it returns a string that meets the right condition and return 4 if it fails.

The best would be to have this run in a BackgroundWorker and keep a timer to kill the BackgroundWorker after 60 seconds, but if the mRumba.GetScreen2 call accesses the UI, that won't work (two threads cannot access the same window handle.

It may be better to use the main thread for the processing and launch a secondary thread that interrupts the main thread after 60 seconds, then catch the ThreadAbortException from the main thread, call Thread.ResetAbort and then return 4. This is similar to what you are doing, except it detects the main thread has been stopped for too long from a secondary thread to exit the current mRumba.GetScreen2 call. Of course, you will have to keep a status variable shared between the threads so you don't kill the thread when it already finished what it was doing or some other situation.

Btw, this is a hack and I'm pretty sure the makers of the class you use must have made a property that tells you a call to mRumba.GetScreen2 will block somehow. Maybe the mRumba.GetScreen2 call depends on there being a second screen connected to the computer and you should check if this prerequisite is correct, else just return 4 or something.

PS. Would it be possible that InStr returns -1 when the string cannot be found and the loop simply run an infinite number of times?
 
I am getting the control to function now, thanks to Stonkie's input. I set up a secondary thread for the code.

VB.NET:
Private Sub btnLogon_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLogon.Click
      'initialize threads
      mainThread = Thread.CurrentThread
      logonThread = New Thread(New ThreadStart(AddressOf Logon))
      'start secondary threads
      logonThread.Start()
   End Sub

   Private Sub Logon()
      Dim strText As String

      If logonThread.ThreadState = ThreadState.Running Then
         Me.axRumba.PutScreen2("Tors Here", 15, 2)
         Thread.Sleep(500)
         Me.axRumba.SendKeys(ENTERKEY)
         Thread.Sleep(500)

         strText = Me.axRumba.GetScreen2(5, 1, 78)
         While InStr(strText, "Type your userid", CompareMethod.Text) <= 0
            Thread.Sleep(500)
            strText = Me.axRumba.GetScreen2(5, 1, 78)
         End While
         strText = Nothing

         Me.axRumba.PutScreen2("Acid Here", 7, 24)
         Thread.Sleep(500)
         Me.axRumba.PutScreen2("Password Here", 8, 24)
         Thread.Sleep(500)
         Me.axRumba.SendKeys(ENTERKEY)
         Thread.Sleep(500)

         strText = Me.axRumba.GetScreen2(10, 1, 78)
         While InStr(strText, "AUTOMATED COLLECTIONS", CompareMethod.Text) <= 0
            Thread.Sleep(500)
            strText = Me.axRumba.GetScreen2(10, 1, 78)
         End While
         strText = Nothing

         Me.axRumba.SendKeys(ENTERKEY)
         Thread.Sleep(500)

         strText = Me.axRumba.GetScreen2(3, 1, 78)
         While InStr(strText, "EMPLOYEE ACTIVITY", CompareMethod.Text) <= 0
            Thread.Sleep(500)
            strText = Me.axRumba.GetScreen2(3, 1, 78)
         End While
         strText = Nothing
      End If
   End Sub

I have not yet set up the Backgroundworker for the GetScreen2 function; that's next.

Thanks again Stonkie!!:D
 
Back
Top