非托管代码调用vb.net回调 [英] Unmanaged code calling vb.net callback

查看:154
本文介绍了非托管代码调用vb.net回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将处理COM对象(可能用VB6编写)的事件的vb.net应用程序从框架1.1升级到WPF 2.0 / 3.5

I am upgrading vb.net app that handles the events of a COM object (possibly written in VB6) from framework 1.1 to WPF 2.0/3.5

代码: (为简便起见,简化了对象名称)

The code: (object names simplified for brevity)

public class MyClass
   Private WithEvents serviceMonitor As COMOBJECT.ServiceMonitor

   Public Sub New()
       serviceMonitor = New COMOBJECT.ServiceMonitor()
       serviceMonitor.Connect([some ip address])
   End Sub

   Private Sub ServiceMonitor_ServiceConnectionUp(ByVal MonitorId As Integer, ByVal UserArg As Integer) _ 
        Handles serviceMonitor.ServiceConnectionUp

        Debug.WriteLine("connection up!")
   End Sub

    ' other similar handlers omitted
End Class

应用程序将以是预期的,但是在几秒钟之内,我就会出现访问冲突。尽管基本运行良好,但基本的回调代码类似于.net 1.1版本。

The app will get the callbacks as expected, however within a few seconds I get an Access Violation. The basic callback code is similar to the .net 1.1 version although it ran perfectly.

根据我对错误的研究,这是由垃圾收集器移动东西引起的。由于我没有将任何要处理的对象传递给DLL,所以我猜想回调是问题所在。其他人通过使用< UnmanagedFunctionPointer(CallingConvention.Cdecl)> 和/或Marshal.GetFunctionPointerForDelegate的委托来解决此问题。

According to my research on the error, it is caused by the garbage collector moving things around. Since I am not passing the DLL any objects to manipulate, I am guessing that the callbacks are the issues. Other folks have solved this via a delegate with <UnmanagedFunctionPointer(CallingConvention.Cdecl)> and/or Marshal.GetFunctionPointerForDelegate.

不幸的是,我发现的所有示例都是DLL具有某种SetCallback(IntPtr)方法的情况。我正在使用WithEvents和Handles关键字。这是我的尝试(请注意,我删除了Handles关键字,以便可以使用AddHandler:

Unfortunately, all the examples I have found are cases where the DLL has some sort of SetCallback(IntPtr) method. I am using WithEvents and the Handles keyword. Here is my attempt (note that I removed the Handles keyword so that I can use AddHandler:

<UnmanagedFunctionPointer(CallingConvention.Cdecl)> _
   Delegate Sub ServiceMonitor_ServiceConnectionUpDelegate(ByVal MonitorId As Integer, ByVal UserArg As Integer)

public class MyClass
   Private WithEvents serviceMonitor As COMOBJECT.ServiceMonitor

   Public Sub New()
       serviceMonitor = New COMOBJECT.ServiceMonitor()
       del = New ServiceMonitor_ServiceConnectionUpDelegate(AddressOf ServiceMonitor_ServiceConnectionUp)
       AddHandler serviceMonitor.ServiceConnectionUp, del ' <--- Error here
       serviceMonitor.Connect([some ip address])
   End Sub

   Private Sub ServiceMonitor_ServiceConnectionUp(ByVal MonitorId As Integer, ByVal UserArg As Integer) 

        Debug.WriteLine("connection up!")
    End Sub

    ' other similar handlers omitted
End Class

我在AddHandler行上遇到的错误是: Value of类型MyClass.ServiceMonitor_ServiceConnectionUpDelegate无法转换为COMOBJECT._IServiceMonitorEvents_ServiceConnectionUpEventHandler

The error I am getting on the AddHandler line is: "Value of type MyClass.ServiceMonitor_ServiceConnectionUpDelegate cannot be converted to COMOBJECT._IServiceMonitorEvents_ServiceConnectionUpEventHandler"

当我将鼠标悬停在上述事件处理程序上时,其签名为:
代表Sub _IServiceMonitorEvents_ServiceConnectionUpEventHandler(ByVal MonitorId为整数,ByVal UserArg为整数)

When I mouse hover the mentioned Event Handler it has a signature of: Delegate Sub _IServiceMonitorEvents_ServiceConnectionUpEventHandler(ByVal MonitorId As Integer, ByVal UserArg As Integer)

签名是相同的,所以我不确定问题出在哪里。

The signatures are identical so I'm not sure what the problem is.

问题1:如何以这种方式在AddHandler中使用委托?
问题2:是否需要涉及 Marshal.GetFunctionPointerForDelegate()吗?

Question 1: How do I use a delegate with AddHandler in this fashion? Question 2: Does Marshal.GetFunctionPointerForDelegate() need to be involved? It returns an IntPtr but AddHandler wants a delegate.

预先感谢。

推荐答案

尽管我还不能100%地确定问题已得到解决,但是到目前为止,我还没有任何访问冲突。

Although I am not yet 100% certain that the issue is fixed, so far I haven't had any more access violations.

基本上,我删除了WithEvents关键字,以防止VB使用其自己的COM-> .net错误处理,而是使用库中用于C ++客户端的方法。我使用了< UnmanagedFunctionPointer(CallingConvention.Cdecl)> 并将库传递给 Marshal.GetFunctionPointerForDelegate IntPtr。我还保留了对IntPtr的引用,尽管它可能已被矫kill过正。

Basically I removed the WithEvents keyword to prevent VB from using its own COM -> .net error handling and instead used the methods in the library intended for C++ clients. I used the <UnmanagedFunctionPointer(CallingConvention.Cdecl)> and passed the library a Marshal.GetFunctionPointerForDelegate IntPtr. I also kept a reference to the IntPtr althought it may have been overkill.

我很困惑,因为WithEvents处理程序在.net中工作得很好,我不得不经历所有这些事情。 1.1。主要区别在于我使用的是表单而不是类来处理回调。

I am confused that I had to go through all this since the WithEvents handlers worked perfectly in .net 1.1. The main differences was that I used a form to handle the callbacks rather than a class.

一个挥之不去的问题是,当我关闭应用程序时,调试器有时仍会运行形成。我希望这只是一个调试器怪癖。

One lingering issue is the fact that the debugger sometimes stays running when I close the apps form. I am hoping it is just a debugger quirk.

这篇关于非托管代码调用vb.net回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆