开发者

Callback from Delphi DLL to C# - only works in idle winform or using app.doevents?

开发者 https://www.devze.com 2023-02-25 17:00 出处:网络
I give up, I have to write and ask; I\'m using an unmanaged DLL written in Delphi, which asynchronously invokes a (parameterless) callback passed to it whenever an event occurs in the hardware it is d

I give up, I have to write and ask; I'm using an unmanaged DLL written in Delphi, which asynchronously invokes a (parameterless) callback passed to it whenever an event occurs in the hardware it is developed to monitor.

What I do in C# is I keep a static reference to a created delegate, which is then passed as parameter to the start method on the Delphi side. This tells the DLL to notify me using the callback, whenever there is new data to fetch, using a GetData method.

All works fine, real fine, until I try to do the exact same thing in a console app, or in a windows service. Or if I create and call the DLL related methods on a separate thread without letting that thread spin doing Application.DoEvents(). Usually people with similar problems seem to have had problems with the GC or cal开发者_Go百科ling conventions, but having (attempted to) secured against GC issues by keeping the delegate ref I stand without further clues on how to solve this.

I'm assuming I'm missing something paramount in how the CLR invokes my callbacks after the DLL calls the thunk provided to connect to my callback handler.

The declarations of my DLL imports look like this:

    [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;

And the call setting up the callback:

        UInt32 result = Start(engineCallback);

Got clues? What's with the need for DoEvents? Any feedback is really appreciated, been trying research this for a few days now, without any indications on progress. /J


It's hard to tell without seeing the native code, but I would assume that the code on the native side depends on a message loop being processed on the thread that calls Start? e.g. because it's using a TTimer or similar?

Once the call to Start has returned, there is only 2 ways how any code can get executed inside that DLL. Either a new thread was started, or a timer or some other mechanism has been registered which depends on window messages.

EDIT:

Another possibility:

If the native DLL is using cross-process COM in an STA (single threaded apartment) then COM depends on a working message loop.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号