Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Delphi DLL回调到C#-仅在空闲winform或使用app.doevents时有效?_C#_Delphi_Service_Callback - Fatal编程技术网

从Delphi DLL回调到C#-仅在空闲winform或使用app.doevents时有效?

从Delphi DLL回调到C#-仅在空闲winform或使用app.doevents时有效?,c#,delphi,service,callback,C#,Delphi,Service,Callback,我放弃了,我不得不写和问;我使用的是一个用Delphi编写的非托管DLL,它在开发用于监视的硬件中发生事件时异步调用传递给它的(无参数)回调 我在C#中所做的是保留对已创建委托的静态引用,然后将其作为参数传递给Delphi端的start方法。这告诉DLL使用回调通知我,只要有新数据要获取,就使用GetData方法 一切都很好,非常好,直到我尝试在控制台应用程序或windows服务中执行完全相同的操作。或者,如果我在一个单独的线程上创建并调用与DLL相关的方法,而不让该线程旋转doing Appl

我放弃了,我不得不写和问;我使用的是一个用Delphi编写的非托管DLL,它在开发用于监视的硬件中发生事件时异步调用传递给它的(无参数)回调

我在C#中所做的是保留对已创建委托的静态引用,然后将其作为参数传递给Delphi端的start方法。这告诉DLL使用回调通知我,只要有新数据要获取,就使用GetData方法

一切都很好,非常好,直到我尝试在控制台应用程序或windows服务中执行完全相同的操作。或者,如果我在一个单独的线程上创建并调用与DLL相关的方法,而不让该线程旋转doing Application.DoEvents()。通常,有类似问题的人似乎在GC或调用约定方面有问题,但他们(试图)通过保持委托ref I的状态来防止GC问题,而没有关于如何解决此问题的进一步线索

我假设在DLL调用提供的thunk以连接到回调处理程序之后,CLR如何调用我的回调中缺少了一些至关重要的东西

my 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);
有线索吗?为什么需要做这些事?任何反馈都是非常感谢的,我们已经尝试了几天,没有任何进展迹象。
/J

如果看不到本机代码,很难判断,但是我假设本机端的代码取决于调用Start?的线程上正在处理的消息循环?e、 因为它使用的是TTimer或类似产品

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

编辑:

另一种可能性:


如果本机DLL在STA(单线程单元)中使用跨进程COM,那么COM依赖于一个工作的消息循环。

如果没有看到本机代码,很难判断,但我假设本机端的代码依赖于调用Start?的线程上正在处理的消息循环?e、 因为它使用的是TTimer或类似产品

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

编辑:

另一种可能性:



如果本机DLL在STA(单线程单元)中使用跨进程COM,则COM依赖于工作消息循环。

给定代码没有线索。你是说它需要一个winform来运行。也许代码需要一个winform消息队列才能在Delphi端运行?Delphi开发人员不这么认为,他在服务(以及其他)中使用它没有问题。Delphi服务有一个活动的消息泵。@Marjan有趣!这个消息泵对DLL响应从另一个DLL调用它的能力至关重要吗?我会这么说。Delphi服务中的消息泵是执行DLL中代码的机制。请参阅Thorsten的答案,了解执行DLL代码的两种方式。给定代码没有任何线索。你是说它需要一个winform来运行。也许代码需要一个winform消息队列才能在Delphi端运行?Delphi开发人员不这么认为,他在服务(以及其他)中使用它没有问题。Delphi服务有一个活动的消息泵。@Marjan有趣!这个消息泵对DLL响应从另一个DLL调用它的能力至关重要吗?我会这么说。Delphi服务中的消息泵是执行DLL中代码的机制。关于执行DLL代码的两种方式,请参见Thorsten的回答。我将调查Delphi DLL中是否有这样的组件在使用。听起来确实是个合理的解释。将Application.DoEvents放在服务的内部线程循环上可以解决这个问题。我得到的总体印象是,这不是一个很好的解决方法,但我想它同时也能工作。如果某个库需要一个工作消息循环,那么它就需要一个工作消息循环。这并非不常见的要求(例如,如果您将COM与STA一起使用,同样适用)。但这是一个需要明确记录的要求。我明白了。没有涉及到COM。从DLL调用我的回调,作为对UDP通信库中断驱动回调的响应。据我所知,不应该依赖于消息泵。但我必须承认,我对这一切如何“依附”的理解非常有限。基本问题:您希望engineCallback在调用Start的同一线程上被调用吗?如果是,则消息泵送是该(或其他)本机库“闯入”该线程以调用回调的唯一方法。此外,托管代码和本机代码之间不涉及COM,但这并不保证本机代码在内部不使用COM。如果您愿意接受回调可以发生在不同线程的上下文中,那么本机代码可以启动自己的线程并在该上下文中进行回调。我明白了!这就解释了。尽管我关心的是它可能是任何线程,但另一个线程更倾向于引用sys.win.forms并在app.doevents上旋转以使事情正常运行。非常感谢你的妙语。现在事情似乎清楚了。我将调查Delphi DLL中是否有这样的组件在使用。听起来确实是个合理的解释。将Application.DoEvents放在服务的内部线程循环上可以解决这个问题。我总的印象是这不是一个很好的例子