等待后读取事件参数
本文关键字:参数 事件 读取 等待 | 更新日期: 2023-09-27 17:56:46
我有一个用于TCP通信的硬件组件。控制它的类有 3 个作业:触发设备,侦听传入消息并在收到消息时引发event
:
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
}
}
此类用于view-model
内的循环中:
public class MainViewModel
{
private static EventWaitHandle hardwareWaiter =
new EventWaitHandle(false, EventResetMode.AutoReset);
private Hardware hardware = new Hardware();
//what i'm doing now is holding a field for incoming event results
private string hardwareResult;
public MainViewModel()
{
hardware.OnHardwareMessage += hardware_OnHardwareMessage;
while (true)
{
hardware.Trigger();
if (hardwareWaiter.WaitOne(10000))
{
//is it possible to read the event argument here?
//do something with the event argument
someObservableCollection.Add(hardwareResult);
//clear the value
hardwareResult = string.Empty;
}
else
{
throw new Exception("Hardware did not respond on time");
}
}
}
//event listener for hardware events
private void hardware_OnHardwareMessage(string message)
{
hardwareResult = message;
hardwareWaiter.Set();
}
}
我所做的是触发设备并等待长达 10 秒的响应。我现在正在做的是持有一个类范围的字段,分配在事件侦听器内收到的消息,在循环内部读取它并清除它。
我的问题是是否有任何内置机制可以让我在发出EventWaitHandle
信号后(在事件侦听器外部)直接读取事件参数。
我不会基于事件。也许您的侦听器应该公开一个表示传入消息流的BlockingCollection
。然后,读者可以在超时的情况下从该集合中获取。如果超时命中,则不会获取和丢失任何消息(这是您现在拥有的争用条件)。
如果您坚持使用事件,请使用闭包来线程消息状态:
string hardwareResult = null;
Action handler = (...) =>
{
hardwareResult = message;
hardwareWaiter.Set();
};
hardware.OnHardwareMessage += handler;
这样,您只需要一个局部变量,其范围比字段更严格。
还有一个常见的TCP错误:你假设阅读整个消息。您可以一次读取一个字节。