C# 等待后读取事件参数
我有一个用于TCP通信的硬件组件。控制它的类有3个作业:触发设备、侦听传入消息并在收到消息时引发C# 等待后读取事件参数,c#,wpf,events,.net-4.5,waithandle,C#,Wpf,Events,.net 4.5,Waithandle,我有一个用于TCP通信的硬件组件。控制它的类有3个作业:触发设备、侦听传入消息并在收到消息时引发事件: public class Hardware { public event Action<string> OnHardwareMessage; private NetworkStream stream = new NetworkStream(); public Hardware() { Task.Factory.StartNew(()
事件
:
public class Hardware
{
public event Action<string> OnHardwareMessage;
private NetworkStream stream = new NetworkStream();
public Hardware()
{
Task.Factory.StartNew(() => { Listen(); });
}
private void Listen()
{
//listen to TCP port and raise an event when a message is received
byte[] bytes = new byte[1024];
int bytesRead = stream.Read(bytes, 0, bytes.Length);
string response = Encoding.ASCII.GetString(bytes, 0, bytesRead);
if (OnHardwareMessage != null)
OnHardwareMessage(response);
}
public void Trigger()
{
//Trigger the hardware component
//the response usually takes up to 5 seconds to arrive
}
}
我所做的是触发设备,并等待10秒钟的响应。我现在要做的是保存一个类范围的字段,分配在事件侦听器中接收的消息,在循环中读取并清除它。我的问题是,是否有任何内置机制可以让我在发出
EventWaitHandle
信号后(在事件侦听器外部)直接读取事件参数。我不会基于事件。也许您的侦听器应该公开表示传入消息流的BlockingCollection
。然后,读者可以在超时的情况下从该集合中获取数据。如果超时到达,则不会接收并丢失任何消息(这是您目前的竞争条件)
如果坚持使用事件,请使用闭包来线程化消息状态:
string hardwareResult = null;
Action handler = (...) =>
{
hardwareResult = message;
hardwareWaiter.Set();
};
hardware.OnHardwareMessage += handler;
这样,您只需要一个局部变量,它的作用域比字段更紧密
还有一个常见的TCP错误:您假设要读取整个消息。您可以一次读取一个字节。我不会以事件为基础。也许您的侦听器应该公开表示传入消息流的
BlockingCollection
。然后,读者可以在超时的情况下从该集合中获取数据。如果超时到达,则不会接收并丢失任何消息(这是您目前的竞争条件)
如果坚持使用事件,请使用闭包来线程化消息状态:
string hardwareResult = null;
Action handler = (...) =>
{
hardwareResult = message;
hardwareWaiter.Set();
};
hardware.OnHardwareMessage += handler;
这样,您只需要一个局部变量,它的作用域比字段更紧密
还有一个常见的TCP错误:您假设要读取整个消息。您可以一次读取一个字节。您已经在设置
硬件结果
,您不能引用它吗?如果在事件处理程序之前执行WaitOne
块,然后,也许你可以把你的代码放在hardware\u OnHardwareMessage
方法中,而不是放在WaitOne
块中?@MikeEason这就是我现在要做的,但是如果有多个事件侦听器,最好不用处理所有这些字段。不幸的是,我无法将代码放入事件处理程序中,因为结果正在被其他字段使用。您已经在设置hardwareResult
,您不能引用它吗?如果在事件处理程序之前执行WaitOne
块,然后,也许你可以把你的代码放在hardware\u OnHardwareMessage
方法中,而不是放在WaitOne
块中?@MikeEason这就是我现在要做的,但是如果有多个事件侦听器,最好不用处理所有这些字段。不幸的是,我无法将代码放入事件处理程序中,因为结果正在被其他字段使用。您已经在设置hardwareResult
,您不能引用它吗?如果在事件处理程序之前执行WaitOne
块,然后,也许你可以把你的代码放在hardware\u OnHardwareMessage
方法中,而不是放在WaitOne
块中?@MikeEason这就是我现在要做的,但是如果有多个事件侦听器,最好不用处理所有这些字段。不幸的是,我无法将代码放入事件处理程序中,因为结果正在被使用,并且被其他一些字段使用