CallByName和Invoke不是异步函数,所以我不能使用如下明显的语法异步调用它们:
rv = await CallByName(objScripts, txtScript.Text, CallType.Method)显然,我是唯一一个需要这样做的人,所以互联网上没有答案。
我的用例是用vb.net编写了数百个数据库转换脚本。我有一个数据库,其中的脚本处理哪个数据库。然后,我的代码读取数据库,并在更新的数据库到达时处理每个脚本,或者我可以从UI中的下拉列表中选择脚本并以这种方式运行它。
现在我需要运行其中的一些脚本异步,这样我就可以使用PuppeteerSharp来抓取一些数据,而不是使用数据库。
那我该怎么做呢?
发布于 2022-03-07 20:44:11
只需将结果转换为Task和await it
rv = Await DirectCast(CallByName(objScripts, txtScript.Text, CallType.Method), Task)发布于 2022-03-07 20:11:45
好吧,弄清楚了。
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)类型将其转换为一个可接受的方法。
您还需要添加异步调用的方法,但您可以将不需要的方法单独放在一起,这样就可以很好地工作。
编辑:
就快到了。当我试图从没有设置为异步的其他函数返回一个值时,就会出现问题。等待期望任务(为Integer),但非异步函数只返回Integer和我得到一个运行时错误。
因此,我想出了如何使用反射来确定方法是否是异步的。我发现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 Ifhttps://stackoverflow.com/questions/71386744
复制相似问题