简体   繁体   English

使用C ++触发事件并在C#中处理它们

[英]Firing events in C++ and handling them in C#

I have an industrial computer with some Digital I/O pins. 我有一台带有一些数字I / O引脚的工业计算机。 The manufacturer provides some C++ libraries and examples to handle pin status change. 制造商提供了一些C ++库和示例来处理引脚状态更改。

I need to integrate this events onto a C# application. 我需要将这些事件集成到C#应用程序中。 AFAIK the most simple way to perform this is: AFAIK执行此操作的最简单方法是:

  1. Make a managed C++/CLI wrapper for the manufacturer libraries that fires events when interruptions are issued from the DIO pins. 为从DIO引脚发出中断时触发事件的制造商库创建托管C ++ / CLI包装器。
  2. Reference that wrapper and handle the events in the C# part as it they were normal C# events. 引用包装并处理C#部分中的事件,因为它们是正常的C#事件。

I have tried to make this work with some mock objects with no luck. 我试图用一些没有运气的模拟对象来完成这项工作。 From the docs, the function EventHandler should do most of the "dirty work" in my case. 从文档中,函数EventHandler应该完成我案例中的大部分“脏工作”。 Following info available in old threads and the EventHandler example in the MSDN docs I ended up with this test code: 以下有关旧线程中的信息以及MSDN文档中的EventHandler示例,我最终得到了以下测试代码:

C++/CLI C ++ / CLI

using namespace System;

public ref class ThresholdReachedEventArgs : public EventArgs
{
public:
    property int Threshold;
    property DateTime TimeReached;
};

public ref class CppCounter
{
private:
    int threshold;
    int total;

public:
    CppCounter() {};

    CppCounter(int passedThreshold)
    {
        threshold = passedThreshold;
    }

    void Add(int x)
    {
        total += x;
        if (total >= threshold) {
            ThresholdReachedEventArgs^ args = gcnew ThresholdReachedEventArgs();
            args->Threshold = threshold;
            args->TimeReached = DateTime::Now;
            OnThresholdReached(args);
        }
    }

    event EventHandler<ThresholdReachedEventArgs^>^ ThresholdReached;

protected:
    virtual void OnThresholdReached(ThresholdReachedEventArgs^ e)
    {
        ThresholdReached(this, e);
    }
};

public ref class SampleHandler
{
public:
    static void c_ThresholdReached(Object^ sender, ThresholdReachedEventArgs^ e)
    {
        Console::WriteLine("The threshold of {0} was reached at {1}.",
            e->Threshold, e->TimeReached);
        Environment::Exit(0);
    }
};

void main()
{
    return;
    CppCounter^ c = gcnew CppCounter(20);
    c->ThresholdReached += gcnew EventHandler<ThresholdReachedEventArgs^>(SampleHandler::c_ThresholdReached);

    Console::WriteLine("press 'a' key to increase total");
    while (Console::ReadKey(true).KeyChar == 'a') {
        Console::WriteLine("adding one");
        c->Add(1);
    }
}

C# C#

using System;

namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        CppCounter cc = new CppCounter(5);
        //cc.ThresholdReached += cs_ThresholdReached; //<--This is the offending line


        Console.WriteLine("press 'a' key to increase total");
        while (Console.ReadKey(true).KeyChar == 'a')
        {
            Console.WriteLine("adding one");
            cc.Add(1);
        }
    }

    static void cs_ThresholdReached(object sender, ThresholdReachedEventArgs e)
    {
        Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached);
        Environment.Exit(0);
    }
}

class Counter
{
    private int threshold;
    private int total;

    public Counter(int passedThreshold)
    {
        threshold = passedThreshold;
    }

    public void Add(int x)
    {
        total += x;
        if (total >= threshold)
        {
            ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
            args.Threshold = threshold;
            args.TimeReached = DateTime.Now;
            OnThresholdReached(args);
        }
    }

    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
    {
        EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
}

  public class ThresholdReachedEventArgs : EventArgs
    {
        public int Threshold { get; set; }
        public DateTime TimeReached { get; set; }
    }
}

What am I doing wrong? 我究竟做错了什么? Is it something I am missing? 这是我缺少的东西吗?

  public class ThresholdReachedEventArgs : EventArgs

The code is correct, except for this minor glitch. 代码是正确的,除了这个小故障。 You accidentally re-declared this class in your C# code. 您不小心在C#代码中重新声明了此类。 Now there are two , one from your C++/CLI project and another from your C# project. 现在有两个 ,一个来自您的C ++ / CLI项目,另一个来自您的C#项目。 That is a problem, type identity in .NET is not just determined by the namespace name and class name, it also includes the assembly it came from. 这是一个问题,.NET中的类型标识不仅仅由命名空间名称和类名决定,它还包括它来自的程序集。

So these are two distinct types, the compiler tries to tell you that the C# version of it is not the correct one. 所以这些是两种不同的类型,编译器试图告诉你它的C#版本不正确。 That they have the same name doesn't exactly help you decode the error message :) 它们具有相同的名称并不能完全帮助您解码错误消息:)

Very easy to fix, simply delete the class declaration from your C# code. 很容易修复,只需从C#代码中删除类声明。 Now the compiler will use the C++/CLI version of it. 现在编译器将使用它的C ++ / CLI版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM