2011-04-14 36 views
1

我放弃了,我不得不写下来并提问;我正在使用Delphi编写的非托管DLL,它在开发监视的硬件中发生事件时异步调用传递给它的(无参数)回调。从Delphi DLL回调到C# - 只适用于空闲的winform或使用app.doevents?

我在C#中做的事情是保持对创建委托的静态引用,然后将其作为参数传递给Delphi端的start方法。这告诉DLL使用回调通知我,每当有新数据要读取时,使用GetData方法。

所有工作都很好,真的很好,直到我尝试在控制台应用程序或Windows服务中执行完全相同的操作。或者,如果我创建并在单独的线程上调用DLL相关方法而不让该线程执行Application.DoEvents()。通常情况下,有类似问题的人似乎在GC或调用约定方面存在问题,但通过让代表参考文献站在原位,没有进一步的线索来解决GC问题。

我假设我在DLL调用连接到我的回调处理程序提供的thunk后CLR调用我的回调时丢失了一些至关重要的东西。

我的DLL进口的声明看起来是这样的:

[DllImport("TheDelphiApi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
    private static extern UInt32 Start(MulticastDelegate callback); 

    [DllImport("TheDelphiApi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
    private static extern void GetData(byte[] recdata); 

    public delegate void EngineCallbackHandler();      

    private static EngineCallbackHandler engineCallback; 

和呼叫建立回调:

 UInt32 result = Start(engineCallback); 

得到了线索?什么是DoEvents的需要?任何反馈真的很感激,一直试图研究这几天,没有任何迹象表明进展。 /J

+0

没有提供给定代码的线索。你说它需要一个winform来运行。也许代码需要一个winform消息队列在Delphi端运行? – CodingBarfield 2011-04-14 10:16:42

+0

不是根据德尔福开发人员,他使用它在服务(而不是没有问题)。 – barbatron 2011-04-14 10:59:25

+0

德尔福服务具有主动消息泵。 – 2011-04-14 12:36:52

回答

1

很难说没有看到本机代码,但我会假设本机端的代码取决于调用开始的线程上正在处理的消息循环?例如因为它使用TTimer或类似的?

一旦对Start的调用返回,只有2种方法可以在DLL中执行任何代码。一个新的线程被启动,或者一个定时器或其他机制已经被注册,这取决于窗口消息。

编辑:

另一种可能性:

如果本地DLL使用跨进程COM中的STA(单线程单元),然后COM取决于工作消息循环。

+0

我会调查是否有这样的组件在Delphi DLL的某处使用。当然听起来像一个似是而非的解释。将Application.DoEvents放在服务的内部线程循环中可解决问题。我总体上觉得这不是一个很好的解决方法,但我猜它在这个时候是有效的。 – barbatron 2011-04-14 13:10:19

+0

那么,如果某个库需要一个工作消息循环,那么它需要一个工作消息循环。这不是一个不常见的要求(例如,如果您与STA一起使用COM,也是如此)。但这是一个需要明确记录的要求。 – 2011-04-14 23:13:24

+0

我明白了。没有涉及到COM。我的回调从DLL中调用,作为对来自UDP通信库的中断驱动回调的响应。所以据我了解,不应该依赖消息泵。但是我不得不承认,我对这一切“粘附”如何非常有限的理解。 – barbatron 2011-04-15 07:45:35