程序被tcp客户端和Timer c#搞砸了

时间:2016-11-15 02:57:36

标签: c# tcp timer

我正在通过Tcp与多个设备进行通信。

我有一个每3秒运行一次的计时器:

readingTimer = new System.Timers.Timer(3000);
readingTimer.Elapsed += ReadingTimer_Elapsed;
readingTimer.Enabled = true;

然后我迭代已发生事件中的设备列表并尝试与它们中的每一个建立连接:

private void ReadingTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
      foreach (var device in Devices)
      {
          Console.WriteLine($"Reading device {device.number}");
          ReadDevice(device);
      }
}

最后,ReadDevice方法创建了一个tcp客户端并尝试读取一些数据:

private string ReadDevice(Device device)
{
     using (TcpClient client = new TcpClient(device.Ip, device.Port))
     {
         //Read Data
         //Return Data
     }
}

问题是我只是在读第一个设备,第二个设备上的迭代永远不会进入。无论我的列表中有多少设备,我总会得到“读取设备1”。

其他信息: 如果无法访问ip,则程序会卡在

using (TcpClient client = new TcpClient(device.Ip, device.Port))

直到超时。之后,迭代被卡住,终止;它不会移动到迭代中的下一个设备。 我在ReadingTimer_Elapsed with

中有一个try / catch
catch
{
    //Log error message
    continue;
}

1 个答案:

答案 0 :(得分:1)

构造函数在进程中进行同步连接,类将阻塞直到它连接或失败。

它可能在事后重新启动迭代,因为当它被阻塞时,计时器线程再次被触发。您的try / catch块必须处理连接错误外部循环,以便捕获第一个错误并退出而不完成设备循环。这就是您始终只看到第一个连接的原因。

在我看来,这不是处理连接的好方法。你对碰撞持开放态度。你应该做的是管理每个连接的状态,并在一个可以处理任何连接错误的单独线程中尝试每个连接。这样你可以跟踪它们,如果一个线程已经在你的计时器触发你的计时器,你就不会再次尝试读取它。