task.run 使用由 c++ dll 调用的方法

问题描述 投票:0回答:1

每次

virtual void image_acquired(
    uint16_t bank,                  // Internal image ID, device DDR bank number.
    uint16_t frame,
    int width,
    int height,
    const uint16_t* image,          // pointer immmagine width*height
    bool more_available) override {
    dotnet_callback(bank, frame, width, height, image, more_available);}

由 SDK 调用,我使用包装器来获取所述图像

class dotnet_device : public stn::stn_device {public:

 using image_acquired_callback = void(uint16_t, uint16_t, int, int, const uint16_t*, bool);
 dotnet_device(image_acquired_callback* dotnet_callback) : dotnet_callback(dotnet_callback) {}
private:

  image_acquired_callback* dotnet_callback; 
protected:

virtual void image_acquired(
    uint16_t bank,                  // Internal image ID, device DDR bank number.
    uint16_t frame,
    int width,
    int height,
    const uint16_t* image,          // pointer immmagine width*height
    bool more_available) override {
    dotnet_callback(bank, frame, width, height, image, more_available);

}};

然后在c#方面

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    unsafe public delegate void ImageAcquiredCallback(ushort bank, ushort frame, int width, int height, ushort* image, [MarshalAs(UnmanagedType.I1)] bool moreAvailable);

然后我创建方法

unsafe public  class StnDevice : IDisposable


{//other things
public event ImageAcquiredCallback ImageAcquired;
private unsafe void OnImageAcquired(ushort bank, ushort frame, int width, int height, ushort* image, bool moreAvailable)
        {
            MessageBox.Show("ciao"); // this doesn't appear
            Task.Run(() => ImageAcquired?.Invoke(bank, frame, width, height, image, moreAvailable));}}

消息框在那里,但当我在这种情况下单击按钮使用表单中的方法时,消息框不会出现

   var device = new NativeMethods.StnDevice();
        
        device.connect();
        device.StartAcquisition();

        device.ImageAcquired += Device_ImageAcquired;
        unsafe void Device_ImageAcquired(ushort bank, ushort frame, int width, int height, ushort* image, bool moreAvailable)
        {// image processing with emgucv}
c# c++ dll x86 visual-studio-2019
1个回答
0
投票

我可能遗漏了一些东西,但我看不到本机代码和 C# 代码是如何连接的。我本来期望使用一堆 p/Invoke 代码来向库注册回调,或者使用公开托管类的 C++/CLI 项目。但我没有看到

StnDevice.OnImageAcquired
被使用过。

但似乎还有其他一些问题。请注意,我还没有看到您的 API 文档,因此其中一些内容将基于推测以及其他本机图像捕获 API 工作原理的经验。

private unsafe void OnImageAcquired(ushort bank, ushort frame, int width, int height, ushort* image, bool moreAvailable)
        {
            MessageBox.Show("ciao"); // this doesn't appear
            Task.Run(() => ImageAcquired?.Invoke(bank, frame, width, height, image, moreAvailable));}}

这看起来非常危险,因为它正在捕获一个指针。我假设您仅在回调运行时维护图像指针的所有权。一旦 OnImageAcquired 返回,库就可以释放或重用内存。如果内存被另一个线程使用,这显然不起作用。要解决此问题,您可能应该在执行涉及另一个线程的任何操作之前将图像数据复制到托管内存。或者继续运行您在同一线程上执行的任何处理。

我还假设

OnImageAcquired
将从某些后台线程调用,因此使用像
MessageBox.Show
这样的 UI 方法可能不会像您期望的那样工作。将某些内容写入日志文件或放置断点是查看是否到达该方法的更好方法。只从 UI 线程做 UI 事情。

您可能还需要考虑某种管道或消息队列系统,例如DataFlow,以允许同时处理帧,同时仍然在 UI 线程上按顺序显示结果。

© www.soinside.com 2019 - 2024. All rights reserved.