Implementing timeout on a DLL function

jonny987

New member
Joined
Apr 8, 2012
Messages
1
Programming Experience
1-3
Hey guys,

I have a piece of hardware (USB IO unit) which comes with a DLL to access it. I'm currently having an issue where I'm trying to access the inputs on the hardware, but the DLL function to do this doesn't have a timeout and it's causing my program to freeze sometimes (I think). When it freezes and I press the pause button, the code goes to the following line in DLL wrapper class I have (with the green debugging arrow):
VB.NET:
lRtn = GetInputs(lHandle)
This is a call to a function in the hardware DLL. It won't move past this line and even if I think stop the program, it won't exit and I'll have to restart my computer (I can't kill the process).

I believe the root cause is the piece of equipment is starting to die because of the operating environment and I'm currently awaiting a new unit to confirm this. In the mean time, I was looking for a way to implement a dirty timeout to allow me to continue to use this unit as it still works intermittently. I was thinking of doing this by creating a new thread to call this function and creating my own timeout, after which I kill the thread by calling Thread.Abort.

I've tried this concept with the following bits of code:
VB.NET:
Public Class Class1
    Public Sub KillMeth(ByVal state As Object)
        MsgBox("KillMeth")
    End Sub
End Class
and in the main form (which just has a button):
VB.NET:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim KillMethThread As Thread = New Thread(AddressOf Class1Inst.KillMeth)
        Dim KillMethThreadID As Integer
        With KillMethThread
            .Priority = ThreadPriority.AboveNormal
            .Name = "KillMethThread"
            KillMethThreadID = .ManagedThreadId
            .Start()
        End With
        KillMethThread.Join(5000)


        If KillMethThread.IsAlive Then
            'kill thread
            KillMethThread.Abort()
            KillMethThread.Join(30000)
            MsgBox(KillMethThread.ThreadState)
            MsgBox("thread killed")
        Else
            MsgBox("thread exited")
        End If
    End Sub



This issue I'm having is that Thread.Abort isn't killing the thread - the thread stays active and in the AbortRequested state and the "KillMeth" msgbox is staying up no matter how long I leave it. I have a feeling it's because I'm using a MsgBox which is waiting on user input, but if I can't terminate a thread waiting on a MsgBox I can see myself having the same issue when trying to use the above code to terminate the GetInputs call to the piece of hardware (I don't have it with me right now unfortunately).

Any ideas on what I'm doing wrong? Or alternatively, any ideas on other ways I can implement an external timeout for this DLL function?

Cheers


PS I do have access to the source code for the DLL, but I have no idea what to do with it. The code for that GetInputs function is:

VB.NET:
DLLIMPORT int32_t _stdcall GetInputs(uint32_t Handle){
          
    uint32_t tempInt ;    
    uint32_t inputState ;
    BOOL retry = TRUE ;
    int retryCount = 3 ;
    uint32_t byteCount ;
            
    char rxCommand[10] ;
    char txCommand[10] ;
        
    
    // Send dummy set command
    //
    sprintf(txCommand, "#SSSS\r") ; 
    
    
    // ---------------- send loop -------------------
    while (retry && (retryCount > 0))
    {    
      retry = FALSE ;
      retryCount-- ;
      
      tempInt = (lpfnFT_Write) (Handle, (void*) &txCommand, 6, &byteCount) ;      
      
      if (tempInt != FT_OK)    
      {
       // (lpfnFT_Close) (Handle) ;
        return (-4) ;
      }    
    
      tempInt = (lpfnFT_Read) (Handle, (void*) &rxCommand, 6, &byteCount) ;
    
           
      if (tempInt != FT_OK)
      {
        //(lpfnFT_Close) (Handle) ;
        return (-4) ;             
      }
    
      if (byteCount >= 6)
      {
        // returned data is in the format >IIOO[CR]
        //                 
        if (rxCommand[0] != '>')   // validate response
        {          
         retry = true ;                      
        }else
        {
          // decode response
          //
          inputState = hexcharToNibble(rxCommand[1]) ;
          inputState <<= 4 ;
          inputState |= hexcharToNibble(rxCommand[2]) ;   
          
          if ((inputState > 0xFF) || (inputState < 0))
          {
            // the value is invalid, something went wrong
            //              
            retry = true ;
          }
        }      
        
      }else
      {
        retry = true ;
      }
      
      if (retry == true)
      {
        // purge the RX and TX buffer
        //
        (lpfnFT_Purge) (Handle, (FT_PURGE_RX | FT_PURGE_TX)) ;
      }
    }   
    // --------------------- end send loop ----------------------- 
    
    //(lpfnFT_Close) (Handle) ;
    
    if (retry == true)
    {
       // tried too many times
       // 
                  
       return (-4) ;
    }    
            
    return(inputState) ;          
}

where the lpfnFT* functions are taken from another DLL (which I don't have the source code for but it probably can be found somewhere on the internet as I'm pretty sure it's an open-source library)
VB.NET:
BOOL setupLibrary(){ 
     //debug ("Setup Library") ;


    // Load the FTD2XX.DLL
    //
    hftdiDLL = LoadLibrary(FTDIDLL);
    if (hftdiDLL != NULL)
    {
        //debug("Success. linked to FTD2XX") ;                 
                 
        // Get pointers to the functions in the DLL
        //
        lpfnFT_ListDevices = (FT_ListDevices)GetProcAddress(hftdiDLL, "FT_ListDevices");      
  ...
    }
}
 
Back
Top