CallByName and Invoke are not async functions so I can't call them asynchronously using the obvious syntax like:
rv = await CallByName(objScripts, txtScript.Text, CallType.Method)
Apparently I am the only one to ever need this so no answers on the internet.
My use case is I have hundreds of database transformation scripts written in vb.net. I have a database of which script processes which database. My code then reads the database and processes each script as the updated databases arrive, or I can select the script from a dropdown in my UI and run it that way.
I now need to run some of theses scripts async so I can use PuppeteerSharp to scrape some data rather use a database.
So how do I make that work?
CodePudding user response:
Just cast the result to Task
and await
it
rv = Await DirectCast(CallByName(objScripts, txtScript.Text, CallType.Method), Task)
CodePudding user response:
Ok got it figure out.
Private Async Function RunAScript_Worker(ScriptName As String, objScript As Object) As Task(Of Integer)
Try
Dim result As Task(Of Integer) = CType(objScript.GetType().GetMethod(ScriptName).Invoke(objScript, Nothing), Task(Of Integer))
Await result
Return result.Result
Catch ex As Exception
Throw ex
End Try
End Function
And you call it like this:
rv = Await RunAScript_Worker(ScriptName, ClsContainingMethod)
This uses reflection and .Invoke and by adding Task(Of Integer)
type turns it into an awaitable method.
You also need to add Async the the called method, but you can leave the ones the don't need it alone and it will work fine.
Edit:
Well, almost there. The problem arises when I try to return a value from the other functions that are not set to async. The await expects a Task(of Integer) but the non-async function return just Integer and I get a run time error.
So I figured out how to use reflection do determine if the method was async. I discovered the name paramerer in GetMethod() is case sensitive so for that and other reasons I added check before executing the method. I also like @Charlieface's solution better than mine so:
If Not objScripts.GetType().GetMethod(ScriptName) Is Nothing Then
If objScripts.GetType().GetMethod(ScriptName).ReturnTypeCustomAttributes.ToString.Contains("Task") Then
Return Await DirectCast(CallByName(objScripts, ScriptName, CallType.Method), Task(Of Integer))
Else
Return CallByName(objScripts, ScriptName, CallType.Method)
End If
Else
' Exception handling
End If