Search code examples
vb.netsap-guicancellation-token

VB.Net CancellationToken does not cancel the Task


I do SAP Gui Scripting in VB.Net with .Net Framework 4.8. At some point the SAP will be unresponsive due to circumstances out of my control, and the called function will completely block further execution forever. In this case i want to safely exit the code.

In order to overcome this obstacle where the SAP function call completely blocks execution my approach is to create a New System.Threading.Task, execute the blocking function in it and after a given timeout cancel the operation. I'd also like to be informed if the element had been found.

For this reason i created the following code mostly by reading docs.mycrosoft.com

Dim propablyBlockingFn = Function () 
  Dim found = False

  While not found
    'code that interacts with sap and will either set found to true or completly block execution
  End While

  Return found
End Function

Dim timeout = 5000 'ms
Dim t As Task(Of Boolean) = Task.Run(fn)
Dim cts As New CancellationTokenSource()
Dim token As CancellationToken = cts.Token

Dim taskRef = t.Wait(timeout, token)

If Not taskRef Then
    cts.Cancel()
End If

Dim exists = t.Result 'it will stuck here
t.Dispose()

However, at the point where i try to read the Result of the function, the code wont execute any further and the cancel call does not have any effect.

Does anyone have an idea?


Solution

  • I've found a last resort solution after reading the following answer. Keep in mind that sideeffects may happen. But they would be even worse if in this case i won't abort the Thread.

    Dim taskThread As Thread = Nothing
    Dim propablyBlockingFn = Function () 
      taskThread = Thread.CurrentThread 'Get the Thread the Task is running in
      Dim found = False
    
      While not found
        'code that interacts with sap and will either set found to true or completly block execution
      End While
    
      Return found
    End Function
    
    Dim timeout = 5000 'ms
    Dim t As Task(Of Boolean) = Task.Run(fn)
    
    Dim taskRef = t.Wait(timeout)
    
    If Not taskRef Then
        taskThread.Abort() 'Abort the Thread
    End If
    
    Dim exists = t.Result