如何使用 CallByName 或调用 Async/Await
How do I use CallByName or Invoke with Async/Await
CallByName 和 Invoke 不是异步函数,所以我不能使用如下明显的语法异步调用它们:
rv = await CallByName(objScripts, txtScript.Text, CallType.Method)
显然我是唯一需要这个的人,所以互联网上没有答案。
我的用例是我有数百个用 vb.net 编写的数据库转换脚本。我有一个数据库,其中脚本处理哪个数据库。然后我的代码读取数据库并在更新的数据库到达时处理每个脚本,或者我可以 select 我的 UI 和 运行 下拉列表中的脚本那样。
我现在需要 运行 一些这些脚本异步,这样我就可以使用 PuppeteerSharp 来抓取一些数据,而不是使用数据库。
那么我该怎么做呢?
好的,明白了。
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
你这样称呼它:
rv = Await RunAScript_Worker(ScriptName, ClsContainingMethod)
这使用反射和 .Invoke 并通过添加 Task(Of Integer)
类型将其变成可等待的方法。
您还需要为被调用的方法添加 Async,但您可以保留不需要的方法,它会正常工作。
编辑:
嗯,差不多了。当我尝试 return 来自未设置为异步的其他函数的值时,问题就出现了。 await 需要一个任务(整数),但 non-async 函数 return 只是整数,我得到一个 运行 时间错误。
所以我想出了如何使用反射来确定该方法是否是异步的。我发现 GetMethod() 中的名称参数是区分大小写的,因此出于这个原因和其他原因,我在执行该方法之前添加了检查。我也比我的更喜欢@Charlieface 的解决方案,所以:
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
只需将结果转换为 Task
和 await
它
rv = Await DirectCast(CallByName(objScripts, txtScript.Text, CallType.Method), Task)
CallByName 和 Invoke 不是异步函数,所以我不能使用如下明显的语法异步调用它们:
rv = await CallByName(objScripts, txtScript.Text, CallType.Method)
显然我是唯一需要这个的人,所以互联网上没有答案。
我的用例是我有数百个用 vb.net 编写的数据库转换脚本。我有一个数据库,其中脚本处理哪个数据库。然后我的代码读取数据库并在更新的数据库到达时处理每个脚本,或者我可以 select 我的 UI 和 运行 下拉列表中的脚本那样。
我现在需要 运行 一些这些脚本异步,这样我就可以使用 PuppeteerSharp 来抓取一些数据,而不是使用数据库。
那么我该怎么做呢?
好的,明白了。
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
你这样称呼它:
rv = Await RunAScript_Worker(ScriptName, ClsContainingMethod)
这使用反射和 .Invoke 并通过添加 Task(Of Integer)
类型将其变成可等待的方法。
您还需要为被调用的方法添加 Async,但您可以保留不需要的方法,它会正常工作。
编辑:
嗯,差不多了。当我尝试 return 来自未设置为异步的其他函数的值时,问题就出现了。 await 需要一个任务(整数),但 non-async 函数 return 只是整数,我得到一个 运行 时间错误。
所以我想出了如何使用反射来确定该方法是否是异步的。我发现 GetMethod() 中的名称参数是区分大小写的,因此出于这个原因和其他原因,我在执行该方法之前添加了检查。我也比我的更喜欢@Charlieface 的解决方案,所以:
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
只需将结果转换为 Task
和 await
它
rv = Await DirectCast(CallByName(objScripts, txtScript.Text, CallType.Method), Task)