Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 等待后读取事件参数_C#_Wpf_Events_.net 4.5_Waithandle - Fatal编程技术网

C# 等待后读取事件参数

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(()

我有一个用于TCP通信的硬件组件。控制它的类有3个作业:触发设备、侦听传入消息并在收到消息时引发
事件

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这就是我现在要做的,但是如果有多个事件侦听器,最好不用处理所有这些字段。不幸的是,我无法将代码放入事件处理程序中,因为结果正在被使用,并且被其他一些字段使用