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

2024-03-22

我有一台带有一些数字 I/O 引脚的工业计算机。制造商提供了一些C++库和示例来处理引脚状态变化。

我需要将此事件集成到 C# 应用程序中。据我所知,执行此操作的最简单方法是:

  1. 为制造商库创建一个托管 C++/CLI 包装器,当从 DIO 引脚发出中断时触发事件。
  2. 引用该包装器并处理 C# 部分中的事件,因为它们是普通的 C# 事件。

我试图用一些模拟对象来完成这项工作,但没有成功。从文档来看,在我的例子中,函数 EventHandler 应该完成大部分“脏工作”。根据旧线程中提供的信息以及 MSDN 文档中的 EventHandler 示例,我最终得到了以下测试代码:

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; }
    }
}

我究竟做错了什么?是我缺少什么吗?


  public class ThresholdReachedEventArgs : EventArgs

除了这个小故障之外,代码是正确的。您不小心在 C# 代码中重新声明了此类。现在有two,一个来自您的 C++/CLI 项目,另一个来自您的 C# 项目。这是一个问题,.NET 中的类型标识不仅仅由命名空间名称和类名称确定,还包括它来自的程序集。

因此,这是两种不同的类型,编译器会尝试告诉您它的 C# 版本不是正确的类型。它们具有相同的名称并不能完全帮助您解码错误消息:)

修复起来非常简单,只需从 C# 代码中删除类声明即可。现在编译器将使用它的 C++/CLI 版本。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C++ 中触发事件并在 C# 中处理它们 的相关文章

随机推荐