在 C++ 中触发事件并在 C# 中处理它们
Firing events in C++ and handling them in C#
我有一台带有一些数字 I/O 引脚的工业计算机。制造商提供了一些C++库和示例来处理管脚状态变化。
我需要将这些事件集成到 C# 应用程序中。据我所知,执行此操作的最简单方法是:
- 为制造商库制作托管 C++/CLI 包装器,当从 DIO 引脚发出中断时触发事件。
- 引用包装器并处理 C# 部分中的事件,因为它们是正常的 C# 事件。
我曾尝试使用一些模拟对象来完成这项工作,但没有成功。从文档中,在我的例子中,函数 EventHandler 应该完成大部分 "dirty work" 。按照旧线程中可用的信息和 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# 代码中重新声明了此 class。现在有两个,一个来自您的C++/CLI 项目,另一个来自您的C# 项目。这是一个问题,.NET 中的类型标识不仅由命名空间名称和 class 名称决定,它还包括它来自的程序集。
所以这是两种不同的类型,编译器试图告诉您它的 C# 版本不正确。它们具有相同的名称并不能完全帮助您解码错误消息:)
非常容易修复,只需从 C# 代码中删除 class 声明即可。现在编译器将使用它的 C++/CLI 版本。
我有一台带有一些数字 I/O 引脚的工业计算机。制造商提供了一些C++库和示例来处理管脚状态变化。
我需要将这些事件集成到 C# 应用程序中。据我所知,执行此操作的最简单方法是:
- 为制造商库制作托管 C++/CLI 包装器,当从 DIO 引脚发出中断时触发事件。
- 引用包装器并处理 C# 部分中的事件,因为它们是正常的 C# 事件。
我曾尝试使用一些模拟对象来完成这项工作,但没有成功。从文档中,在我的例子中,函数 EventHandler 应该完成大部分 "dirty work" 。按照旧线程中可用的信息和 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# 代码中重新声明了此 class。现在有两个,一个来自您的C++/CLI 项目,另一个来自您的C# 项目。这是一个问题,.NET 中的类型标识不仅由命名空间名称和 class 名称决定,它还包括它来自的程序集。
所以这是两种不同的类型,编译器试图告诉您它的 C# 版本不正确。它们具有相同的名称并不能完全帮助您解码错误消息:)
非常容易修复,只需从 C# 代码中删除 class 声明即可。现在编译器将使用它的 C++/CLI 版本。