C# 接收到设备控制线程数据事件错误

C# 接收到设备控制线程数据事件错误,c#,multithreading,events,serial-port,task,C#,Multithreading,Events,Serial Port,Task,我和我的同事花了几天的时间寻找解决方案,大多数回复都说要去掉不必要的线程。情况是这样的 我最多控制1-55台设备(取决于用户需求)。我必须大约同时初始化每个设备。我通过对InitializeDevice(deviceNumber)的每次调用执行任务,这将启动每个设备的初始化,然后轮询设备直到完成 SerialPort.Write()override函数是locked,这样一次只能有一个设备写入,所以这不是我的问题(经过彻底测试)。当我为3台设备创建任务时,我很好。当我为4台设备创建任务时,我的串

我和我的同事花了几天的时间寻找解决方案,大多数回复都说要去掉不必要的线程。情况是这样的

我最多控制1-55台设备(取决于用户需求)。我必须大约同时初始化每个设备。我通过对
InitializeDevice(deviceNumber)
的每次调用执行
任务
,这将启动每个设备的初始化,然后轮询设备直到完成

SerialPort.Write()
override函数是
lock
ed,这样一次只能有一个设备写入,所以这不是我的问题(经过彻底测试)。当我为3台设备创建任务时,我很好。当我为4台设备创建任务时,我的串行端口停止正常工作(尽管它在我的同事身上工作,他们有6个内核,而我的4个内核)。
DataReceived
事件在短时间内停止触发,如下所述

Write(command1); // Attempt 1, task 1 fails to get a response when responseTimeout.WaitOne(50) times out
Write(command1); // Attempt 2, task 1 fails to get a response due to 50ms timeout
Write(command1); // Attempt 3, task 1 fails to get a response due to 50ms timeout
Write(command1); // Attempt 4, task 1 fails to get a response due to 50ms timeout
Write(command1); // Attempt 5, task 1 fails to get a response due to 50ms timeout
DataReceived event is triggered and at this point BytesToWrite contains all the data that has been accumulated.
After this initial DataReceived event delay, everything proceeds as expected. (this is one of the biggest reasons that I believe that it is either the creation or starting of the `Task`s that breaks the port)
我们无法摆脱这些任务,因为对于我们的应用程序来说,似乎同时启动非常重要

为了测试创建
任务
s是否是瓶颈,我们尝试创建所有
任务
s,然后同时启动它们,但也不起作用,这使得启动线程似乎是问题所在。 为了测试启动
任务
s是否是问题所在,我们在
InitializeDevice(deviceNumber)
中设置了一个断点,它被调用
SerialPort.Write()
函数之前所做的所有4个
任务
击中。由于所有4个任务都是在编写
之前创建、启动和运行的,因此您可能会认为
任务
不可能成为瓶颈。
当我将
responseTimeout.WaitOne(time)
50
跳到
1000
时,
写入
都成功了,尽管
写入
和触发
接收数据
之间的延迟如下:990ms、6ms、15ms、15ms、16ms等。平均响应时间约为15ms。 我们连接了一个逻辑分析仪,使用和不使用
任务
s,并且响应时间始终大约为5ms,因此我们不会丢失响应,只是事件没有在合理的时间内触发。 我们已尝试将
DataReceived
设置为最高优先级,并将初始化
任务设置为最低优先级,但均无效

一切都指向这一点,即
任务
s或线程创建会占用处理器速度,并阻止
接收到的数据
在合理的时间内触发。我们不能无限期地等待响应,我们必须同时启动所有设备。目前我们已经没有解决方案了


示例代码

public class DeviceControl
{
    private static void Initialize_AllDevices(CustomSerialPort port, List<Device> devices)
    {
        for (int i = 0; i < devices.Count; i++)
        {
            DeviceNumber deviceNumber = i;

            Task.Factory.StartNew(
                () => Initialize_SingleDevice(port, devices, deviceNumber));
        }
    }

    private static void Initialize_SingleDevice(CustomSerialPort port, List<Device> devices, int deviceNumber)
    {
        List<byte> command = devices[deviceNumber].CreateCommand();
        port.Write(command);
    }
}

public class CustomSerialPort : SerialPort
{
    private AutoResetEvent _responseTimeout;

    public CustomSerialPort()
    {
        DataReceived += Read;
        _responseTimeout = new AutoResetEvent(false);
    }

    private void Read(object sender, SerialDataReceivedEventArgs eventArgs)
    {
        // This is what is not reached until Task creation is complete.
        // Parse response
        if (ReadSuccessful())
        {
            _responseTimeout.Set();
        }
    }

    public void Write()
    {
        lock (new object())
        {
            Write(command.ToArray(), 0, command.Count);

            // Wait until response timeout is hit or response is received.
            _responseTimeout.Reset();
            if (!_responseTimeout.WaitOne(50))
            {
                // uh oh
            }
        }
    }
}

公共类设备控制
{
私有静态无效初始化所有设备(CustomSerialPort端口,列出设备)
{
对于(int i=0;i初始化单个设备(端口、设备、设备编号));
}
}
私有静态无效初始化\u SingleDevice(CustomSerialPort端口、列表设备、int deviceNumber)
{
List命令=设备[deviceNumber].CreateCommand();
端口写入(命令);
}
}
公共类CustomSerialPort:SerialPort
{
私人自动存储(u responseTimeout),;
公共CustomSerialPort()
{
数据接收+=读取;
_responseTimeout=新的自动重置事件(假);
}
私有无效读取(对象发送方、SerialDataReceivedEventArgs事件args)
{
//这是在任务创建完成之前无法实现的。
//解析响应
if(ReadSuccessful())
{
_responseTimeout.Set();
}
}
公共空写()
{
锁定(新对象())
{
写入(command.ToArray(),0,command.Count);
//等待响应超时或收到响应。
_responseTimeout.Reset();
如果(!\u responseTimeout.WaitOne(50))
{
//哦
}
}
}
}

仅澄清一下,这些设备是否共享一个串行端口控制?或者他们只是分享一个收到的事件?请张贴实际的代码,而不是仅仅谈论它。这将有助于我们帮助你。祝你好运实际的代码(由于IP,我可以发布的代码)已经包含在内。但是,只有当多个设备以百万波特的速度运行且核心数有限时,问题才会重现。