Can Access get a result from an Async vb.net dll function? (1 Viewer)

chacham

Member
Local time
Today, 07:46
Joined
Oct 26, 2020
Messages
45
I have a VB.NET DLL that uses Async/Await in most of its calls due to using HttpClient (docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) in many of its calls. I now want to call it from Access. After making the DLL COM visible and interopable, and registering it, the call from Access was successful, evidenced by popping up a message box.

However, when calling an Async Function, the code exits at the Await. That is, if the function is:

Code:
Public Async Function test() As Task(of String)
  Dim Result as String
  MsgBox("a")
  String = Await something()
  MsgBox("b")
  Return Result
End Function

The MessageBox showing "a" is seen, but the one for "b" is not and the caller does not see the result. Obviously, that is exactly what it is supposed to do, as that is the entire point of the Await modifier. In VB, however, i can call the function itself with Await, and it will await the result, but it does not look like Access supports the Await keyword.

Is there a way to await the function in Access or in anyway get the results, such as through event handling or a callback? Or do i need to rewrite the DLL to not use HttpClient?
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 06:46
Joined
Feb 28, 2001
Messages
27,172
The question I have is whether, when the thing you are waiting to see actually occurs / arrives / whatever it does, what happens then?

Access has limited abilities to externally synchronize with anything that isn't an I/O function or a clock function. I recall someone trying to establish a callback entry but as I recall, there was some problem in making it work.

Here is the thread: https://www.access-programmers.co.uk/forums/threads/dll-with-callback-problem.305246/

I have no idea if anything (including some of the links) in this thread will help you. But it was a deep dive into the topic of callbacks.
 

chacham

Member
Local time
Today, 07:46
Joined
Oct 26, 2020
Messages
45
when the thing you are waiting to see actually occurs / arrives / whatever it does, what happens then?

Iiuc, the thread returns. But with nothing waiting for it. it drops the return into the nether.

recall someone trying to establish a callback entry but as I recall, there was some problem in making it work.

Perhaps that isn't the best method then. :)
 

chacham

Member
Local time
Today, 07:46
Joined
Oct 26, 2020
Messages
45
I found the answer elsewhere. Instead of awaiting the reply, the dll can raise an event that vba can handle. It just requires declaring IDEventInterface/_IDEventInterface so vba can see it.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 06:46
Joined
Feb 28, 2001
Messages
27,172
Makes perfect sense. Everything running in Windows (and, in fact, Windows itself) is technically event-driven, so this makes for a good approach that should be compatible with a lot of things in Office, not just Access. Congrats on finding your solution.
 

chacham

Member
Local time
Today, 07:46
Joined
Oct 26, 2020
Messages
45
Okay, that did not actually work for the async sub. As soon as await was hit, vba exited, and the vb.net thread died. So, i put a doevents/sleep and looped on a flag set in the event handler.

Here's an example vb.net dll:

Code:
Imports System.Runtime.InteropServices

<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface IDEventInterface
    Sub Message(Text As String)
End Interface

<ComSourceInterfaces(GetType(IDEventInterface))>
Public Class Test
    Event Message(Text As String)

    Async Sub Send_Wait_Send(Text As String)
        RaiseEvent Message("Awaiting")
        Await Task.Delay(1000)
        RaiseEvent Message(Text)
    End Sub

End Class

Here's a vba module that calls the class module:

Code:
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal Milliseconds As LongPtr)

Sub Main()
  Set Events = New Events
End Sub

And here the class module that calls the vb.net dll (named "Events"):

Code:
Private WithEvents Test As Event_Test.Test
Private Received As Boolean

Sub Class_Initialize()
  Set Test = New Event_Test.Test
  Test.Send_Wait_Send "The_Doc_Man"

  Received = False
  Do
   Sleep 500
   DoEvents
  Loop Until Received

End Sub

Sub Test_Message(ByVal Text As String)
  Received = True
  MsgBox Text
End Sub

Does this look okay? Or is there a better way than a doevents/sleep loop?
 

Users who are viewing this thread

Top Bottom