2015-11-19 1 views
0

Я создаю приложение в LabVIEW, которое требует, чтобы я регистрировал события .NET через обратный вызов. API, который мне предоставлен, не содержит публичных событий, поэтому я не могу их правильно зарегистрировать. Кроме того, конструктор, который я пытаюсь создать, не работает. Я очень новичок в обработке событий и C# в целом, поэтому приношу свои извинения, если в моем описании отсутствует что-то.Обработка событий в LabVIEW через C# - Узел конструктора типа PROP.PropEngine не найден

Используя 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) 

у меня нет доступа к исходному коду, поэтому я думал, что я должен вместо этого создать свой собственный класс, с указателем на функцию является свойство/членом класса:

public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc; 

Я думаю, что я мог бы просто написать это как частную функцию без нового класса, но, к сожалению, конечное приложение этого не позволит.

В приложении у меня возникли конфликты классов при попытке передать указатель этой функции конструктору, но я просто подумал, что мне нужно сделать бросок типа, чтобы заставить их работать (ошибка новобранец). Теперь я получаю эту ошибку узла конструктора, и я думаю, что это потому, что указатель, который я отправляю, является плохим указателем.

документация указывает на то, что обработчик события должен принимать два аргумента:

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

sender является объектом, и eventArgs является «структура» своего рода, который содержит все данные о событии.

Проблемы: Моя функция указателя плохая, но я не знаю почему. Кроме того, типы событий не отображаются, поэтому я не могу их учитывать (я думаю).

+0

Я заметил, что ваш PropEvent статичен. Почему это? –

+0

Я не уверен! Разве это не должно быть? – ijustlovemath

+0

Я тоже не уверен. Не могли бы вы добавить публичных членов вашего API к вашему вопросу? Это поможет определить, что делать. –

ответ

1

Есть два основных препятствия в текущем подходе:

  • LabVIEW не может создать делегатов, поэтому он не может построить PropEngine так (в соответствии с вами) его конструктор требует PropEngine.EventHandler делегата.
  • С помощью статического события и обработчика событий ваша программа LabVIEW ограничена одним экземпляром PropEngine.

Ваша идея создания адаптера позволит вам использовать класс PropEngine, просто немного отредактируйте его.

C# Адаптер

Я написал два класса в библиотеке классов (.длл):

  • MockProp - что догадка в вашем API
  • MockPropAdapter - что позволяет LabVIEW, чтобы использовать MockProp класс

Адаптер предоставляет доступ публичного мероприятия, которые LabVIEW могут подписаться с Register Event Callback node. Обратный вызов LabVIEW VI будет вызван, когда событие PropEngine будет поднято до тех пор, пока ваша программа LabVIEW создает адаптер и подписывается на его событие, прежде чем использовать адаптер для создания экземпляра PropEngine.

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 Client

в блок-схеме фрагмент кода ниже, программа LabVIEW:

  1. Создает адаптер
  2. Регистры для события повторителя
  3. использует адаптер для создания MockProp пример
  4. Использует MockProp экземпляра, чтобы поднять его событие
  5. Это когда обработчик VI обрабатывает событие
  6. отписывается от события повторителя
  7. высвобождает MockProp экземпляра
  8. высвобождает адаптер

enter image description here

+0

Вау, спасибо за невероятно подробный пост. Я подробно описал API на форумах LabVIEW: http://forums.ni.com/t5/LabVIEW/Registering-and-Handling-NET-Events-in-LabVIEW/td-p/3219225 – ijustlovemath

+0

К сожалению, под NDA так что лучше всего я могу сделать макет публичного материала. Спасибо, хотя, я собираюсь отметить это как решение. – ijustlovemath