将 VB 函数回调作为参数传递给 .NET

Posted

技术标签:

【中文标题】将 VB 函数回调作为参数传递给 .NET【英文标题】:Pass VB Function callback as parameter to .NET 【发布时间】:2020-10-02 01:52:18 【问题描述】:

Visual Basic 程序的一部分正在移至 .NET dll。

参数调用成功,一切正常。

如何在长时间运行的异步任务后传递 VB6 的回调函数以供 .NET 调用?

在 .NET 中

Public Delegate Function VBCallBackFunc() As Integer

Public Function DoSomething(a As String, b As String, c As String, _
parent As IntPtr, Optional ByVal CallbackAddr As VBCallBackFunc = Nothing) As Boolean Implements _DotNetLib.DoSomething

VB6

result = DotNetLib.DoSomething(strA, strB, strC, Me.hwnd, AddressOf DotNetCallback)

Public Function DotNetCallback() As Long
    MsgBox ("Callback")
End Function

在VB的对象浏览器中:

Function DoSomething(strA As String, strB As String, strC As String,
 parent As Long, [CallbackAddr As VBCallBackFunc]) As Boolean

Member of DotNetLib

但它说“AddressOf 运算符的使用无效”???

【问题讨论】:

DotNetCallback 在类模块中吗? 我尝试移动到类模块,现在是类型不匹配错误:/ 它必须在一个普通的模块中。您引用的错误是在类模块中。 VB6 没有类型化的回调,它们应该是Long。就 VB6 而言,VBCallBackFunc 是什么? 您应该改用 .NET COM 事件。它比原始回调更安全:docs.microsoft.com/en-us/previous-versions/dotnet/… 【参考方案1】:

使用Events相关的cmets是一个不错的选择,但是我更倾向于使用接口,所以这里有一个解决方案。

(手写代码,需要进行语法检查,名称可以清理,仅用于说明目的)

在 .NET 中:

为您的回调创建一个 COM 公开接口:

Public Interface IVBCallBack
   Public Function VBCallBackFunc() As Integer
End Interface

改变你的 DoSomething 是这样的:

Public Function DoSomething(a As String, b As String, c As String, parent As IntPtr, ByVal CallbackAddr As IVBCallBack) As Boolean

在 VB6 中:

result = DotNetLib.DoSomething(strA, strB, strC, Me.hwnd, Me)

(你需要你的类、控件或表单到Implements IVBCallBack

Public Function IVBCallBack_VBCallBackFunc() As Long
    MsgBox ("Callback")
End Function

确保在 .NET 端有一个方法来清理和释放所有引用,因为 .NET 持有对 VB6 对象的引用。

还有一点需要注意。不要在主 UI 线程以外的任何线程上回调 VB6!

【讨论】:

加一个 - AFAICR 在 COM/.Net 互操作中使用事件有点不稳定,所以我会选择这个选项 问题是“对于 .NET 在长时间运行的异步任务后调用”。事件应该保护开发人员免受线程或悬空交叉引用问题(提供 VB 代码泵 windows 消息) 可以在其他线程上调用事件,但可以肯定的是,正如我打开的那样,事件是一个不错的选择。过去我遇到过一些问题,我不记得具体的问题(VB6 现在已经过时了),所以我最终采用了接口方法并且从未回头。 有趣的是,我发现这篇文章 (***.com/questions/18224220/…) 表明我的警告可能为时过早,COM 互操作的魔力会处理线程。 YMMV 这很好用。在 VB6 实现 DotNetLib.IVBCallBack 后,现在在主线程中使用 Invoke 从 .NET 成功调用函数。做得很好,非常感谢!

以上是关于将 VB 函数回调作为参数传递给 .NET的主要内容,如果未能解决你的问题,请参考以下文章

什么是回调函数

如何将回调作为参数传递给另一个函数

下拉列表将参数传递给 vb.net 中的 webmethod

将参数传递给 UIcontrol 回调函数

将额外的参数传递给回调函数

如何通过原始指针将闭包作为参数传递给 C 函数?