Firing events in C++ and handling them in C#

2019-06-25 17:14发布

I have an industrial computer with some Digital I/O pins. The manufacturer provides some C++ libraries and examples to handle pin status change.

I need to integrate this events onto a C# application. AFAIK the most simple way to perform this is:

  1. Make a managed C++/CLI wrapper for the manufacturer libraries that fires events when interruptions are issued from the DIO pins.
  2. Reference that wrapper and handle the events in the C# part as it they were normal C# events.

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. Following info available in old threads and the EventHandler example in the MSDN docs I ended up with this test code:

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#

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?

1条回答
小情绪 Triste *
2楼-- · 2019-06-25 17:46
  public class ThresholdReachedEventArgs : EventArgs

The code is correct, except for this minor glitch. You accidentally re-declared this class in your C# code. Now there are two, one from your C++/CLI project and another from your C# project. 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.

So these are two distinct types, the compiler tries to tell you that the C# version of it is not the correct one. 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. Now the compiler will use the C++/CLI version of it.

查看更多
登录 后发表回答