这个服务器解决方案是最优的吗?

Is this server solution optimal?

我创建了从传感器接收数据的设备(大约 80k 个样本/秒)并通过 TCP/IP 将它们发送到我的 PC 应用程序。问题是有时我的设备会丢失一些数据。我想这是因为当我通过 TCP/IP 发送数据时,处理器需要一些时间来完成,然后他有一段时间没有从传感器接收数据。我注意到,当我在发送数据之前收集一些数据时,发生的次数较少,因此我在 data.Length 高于 30000 时发送数据。感谢您的建议。 有我的服务器代码:

while (true)
{
    if (ClientIsConnected==1)
    {
        value = Convert.ToString(sensor1.Read(0)); ; // Publish the return value 

        DateTime currentDate = DateTime.Now;
        long elapsedTicks = currentDate.Ticks - startDate.Ticks;
        TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
        time = Convert.ToString(elapsedTicks / 100);

        data.Append("[" + value + " " + time + "]" + "/n");
        if (data.Length > 30000)
        {
            serverTcp.Send(socket, Convert.ToString(data));
            data.Clear();
        }
    }   
}

编辑两个不同的线程代码:

object msg = null;

if (ClientIsConnected==1)
{
    var threadTcp = new Thread(() =>
    {
        server.Send(socket, Convert.ToString(data));
    });

    var threadReadAdc = new Thread(() =>
    {
        value = Convert.ToString(Sensor1.Read(0)); ; // Publish the return value
      
        DateTime currentDate = DateTime.Now;
        long elapsedTicks = currentDate.Ticks - startDate.Ticks;
        TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
        time = Convert.ToString(elapsedTicks / 100);

        data = data.Append("[" + value + " " + time + "]" + "\n");
        if (data.Length > 30000)
        {
            msg = Convert.ToString(data);
            data.Clear();
        }
    });
    
    threadReadAdc.Start();
    threadTcp.Start();
}

我会在这里使用类似 BlockingCollection<string> 的东西

https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.blockingcollection-1?view=net-5.0

您可以设置一个字符串集合,在一个线程中写入集合,在另一个线程中读取。读取可以将结果存储在缓冲区中,并在缓冲区足够满时通过 TCP 发送(或者已经过足够的时间 - 这取决于您)。

阻塞集合是线程安全的,读会阻塞直到有东西可读。

例如


var data = new BlockingCollection<string>();

Task taskWrite = Task.Run(() =>
{
    while(true)
    {
        var sensorReading = Convert.ToString(sensor1.Read(0)); // Do your string time/formatting here too - I left it off for clarity
        data.Add(sensorReading);
    }
});

Task taskRead = Task.Run(() => {
    var buffer = List<string>();

    while(true)
    {
        if(buffer.Count > 30000) 
        {
            // Grab contents of buffer and send via TCP
            server.Send(socket, String.Join("\n", buffer));
            buffer.Clear();
        }
        else 
        {
            // Consume the next sensor value from the collection
            buffer.Add(data.Take());
        }
    }
});

如果您想确保不会用值填满内存(例如,如果您的读取速度比写入速度快得多),您还可以在阻塞集合上设置界限。