通过 C# 在 LabVIEW 中处理事件 - 未找到类型 PROP.PropEngine 上的构造函数节点

Event handling in LabVIEW via C#- Constructor Node on type PROP.PropEngine not found

我正在 LabVIEW 中构建一个应用程序,它需要我通过回调注册 .NET 事件。我得到的 API 中没有 public 事件,所以我无法正确注册它们。此外,我尝试创建的构造函数无法正常工作。一般来说,我对事件处理和 C# 还很陌生,所以如果我的描述中有任何遗漏,我深表歉意。

使用与我合作的公司提供的 API,我制作了这个事件处理程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using PROP.PropEngine;
namespace IMTEventHandler
{
    public delegate void PropEngineEventHandlerDelegate(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs);
    public class IMTDelegate
    {
        public static event PROP.PropEngine.EventHandler PropEvent
        {
            add { inner.PropEvent += value; }
            remove { inner.PropEvent -= value; }
        }
        public static void PropEngineEventHandlerFunc(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs)
        {
            return ;
        }
        public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc;
        //Pointer to our Event Handler
    }
}

他们的文档说构造函数接受一个指向事件处理程序的函数指针,例如:

_propEngine = new PropEngine(propEventHandlerFunc)

虽然我无法访问原始代码,所以我认为我应该创建自己的 class,函数指针是 class 的 property/member :

public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc;

我认为我可以将它写成一个私有函数而不用 new class,但不幸的是,最终应用程序不允许这样做。

在应用程序中,当我试图将此函数指针传递给构造函数时遇到了一些 class 冲突,但我只是想我必须进行类型转换才能使它们工作(菜鸟错误)。现在我得到这个构造函数节点错误,我认为这是因为我发送的指针是一个错误的指针。

文档指出事件处理程序应采用两个参数:

void PropEngineEventHandlerFunc(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs)

sender 是一个对象,eventArgs 是一个包含所有事件数据的 'struct' 类型。

问题:我的函数指针坏了,但我不知道为什么。此外,事件类型没有公开,所以我无法解释它们(我认为)。

您当前的方法有两个主要障碍:

  • LabVIEW 无法创建委托,因此无法构造 PropEngine,因为(根据您的说法)其构造函数需要 PropEngine.EventHandler 委托。
  • 通过使用静态事件和事件处理程序,您的 LabVIEW 程序仅限于单个 PropEngine 实例。

您创建适配器的想法将使您能够使用 PropEngine class,只需稍微重构一下即可。

C# 适配器

我在 Class 库 (.dll) 中写了两个 classes:

  • MockProp -- 这是对您 API
  • 的猜测
  • MockPropAdapter -- 允许 LabVIEW 使用 MockProp class

适配器公开了一个 public 事件,LabVIEW 可以使用 Register Event Callback node 订阅该事件。只要您的 LabVIEW 程序创建适配器并在使用适配器创建 PropEngine 实例之前订阅其事件,就会在引发 PropEngine 事件时调用您的 LabVIEW 回调 VI。

using System;

namespace MockProp
{
   // This is my sketch of the API you've been given.
    public class MockProp
    {
       // I'm assuming that the API publishes the event handler's signature.
       public delegate void MockPropEventHandler(object sender, EventArgs args);

       // I'm assuming that the API's event is instance-based and not static.
       private event MockPropEventHandler MockPropEvent;

       // I'm assuming that it's keeping a reference to your event handler.
       private MockPropEventHandler clientHandler;

       public MockProp(MockPropEventHandler eventHandler)
       {
          this.clientHandler = eventHandler;

          // I'm assuming that it also auto-subscribes to the event because it is a constructor parameter.
          this.MockPropEvent += this.clientHandler;
       }

       // Provide an easy way for LabVIEW to trigger the event for demonstration purposes.
       public void NotifyEvent()
       {
          if (this.MockPropEvent != null)
          {
             var args = new EventArgs();
             this.MockPropEvent(sender: this, args: args);
          }
       }

       // Allow the object to be garbage collected by removing all retaining references.
       public void Release()
       {
          this.MockPropEvent -= this.clientHandler;
          this.clientHandler = null;
       }
    }

   // Here's one way to allow LabVIEW to subscribe to and handle private events
   public class MockPropAdapter
   {
      private MockProp mockProp;

      public MockPropAdapter()
      {
         // NOOP
      }

      // LabVIEW can subscribe to this event.
      public event MockProp.MockPropEventHandler MockPropEventRepeater;

      public MockProp CreateMockProp()
      {
         if (this.MockPropEventRepeater == null)
         {
            throw new InvalidOperationException(message:
               "Subscribe to MockPropEventRepeater first. Otherwise, the Prop's event cannot be repeated.");
         }
         else
         {
            this.mockProp = new MockProp(eventHandler: this.MockPropEventRepeater);
            return this.mockProp;
         }
      }

      private void RepeatMockPropEvent(object sender, EventArgs args)
      {
         if (this.MockPropEventRepeater != null)
         {
            this.MockPropEventRepeater(sender, args);
         }
      }
   }
}

LabVIEW 客户端

在下面的框图片段中,LabVIEW 程序:

  1. 创建适配器
  2. 注册转发器事件
  3. 使用适配器创建一个 MockProp 实例
  4. 使用 MockProp 实例引发事件
  5. 这是handler VI处理事件的时候
  6. 取消订阅转发器事件
  7. 释放 MockProp 个实例
  8. 释放适配器