通讯观察线程是个有意思,又是非常实用的功能。
断线重连具体怎么实现呢,很多人都实现过,那么TouchSocket等几个通讯组件中也包含有,都是可以拿来就用。只是,对于高级用户和特别细节操作要求的,是会自定义特别的超时断线业务规则。
首先要有三个方法, start, stop和Restart
/// <summary>
/// 启动
/// </summary>
public bool Start()
{try{//先执行ping 命令KeepServer = true;IPAddress ip = IPAddress.Parse(ComPara.ServerIP);IPEndPoint ipep = new IPEndPoint(ip, ComPara.Port);Tcpsocket.Connect(ipep);processor = new Thread(Communication);processor.IsBackground = true; processor.Start();return true;}catch (Exception ex){KeepServer = false; //ex.LogError();return false;}finally{this.communicationobserve_timer.Enabled = true;}
}/// <summary>
/// 停止服务
/// </summary>
public bool Stop()
{try{IsStop = true;this.communicationobserve_timer.Enabled = false;KeepServer = false;Tcpsocket.Close();Tcpsocket.Dispose();if (processor != null ) {processor.Abort();//解决线程过多情况,因为线程执行Abort,状态是AbortRequested,还是会存在继续执行while (processor.ThreadState != ThreadState.Aborted){ Thread.Sleep(100); }LogHelper.WorkAndInfo($"LB600 停止服务 Stop();");}return true;}catch //(Exception ex){ //ex.LogError();return false;}
}/// <summary>
/// 重新启动
/// </summary>
protected bool ReStart()
{ try{KeepServer = true; //return Start();IPAddress ip = IPAddress.Parse(ComPara.ServerIP);IPEndPoint ipep = new IPEndPoint(ip, ComPara.Port);Tcpsocket.Connect(ipep); //IP和端口processor = new Thread(Communication);processor.IsBackground = true;processor.Start();//DelegateState.InvokeDispatchStateEvent($" {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} {this.DeviceCode}号机器人,恢复连接成功!");//Comm.Speak($" {this.DeviceCode}号机器人,启动重连中");return true;}catch //(Exception ex){KeepServer = false; //ex.LogError();return false;}
}
第二,要有Reconnect()方法
/// <summary>/// 重新创建连接/// </summary>public void ReConnect() {try{if (Init()){ if (ReStart()){LastConnectTime = DateTime.Now; //LastRecTime 在有反馈时才记录Comm.Speak($"{DeviceCode}号设备,掉线后重连成功!");}}}catch (Exception ex){LogHelper.Error("尝试连接" + $" 将在3秒后重新尝试连接...", ex); }}
最重要的是最后这个通讯的超时监测,这里设置就是重联达到的条件,至于两个超时变量如下面定义:
/// <summary>
/// 通讯状态观察
/// </summary>
private void CommunicationObser(object sender, ElapsedEventArgs e)
{try{communicationobserve_timer.Enabled = false;//if (Monitor.TryEnter(lockobj, TimeSpan.FromSeconds(1))){//先判断 机器人是否已经掉线if (LastRecLong > 2) //调试时修改为300, 默认1秒,{//如果接受消息时间已经大于1秒,则认为掉线了if (LastConnectLong > 3) //调试时修改为500, 默认3秒{ //如果车子掉线且连接时间超过3秒则需要重连LogHelper.WriteSendAGVMessLog($"重连 {DeviceCode}号"); //调试时暂时注释掉//ReConnect(); 添加了LastRecTime = DateTime.Now;LastRecTime = DateTime.Now;Comm.Speak($"{DeviceCode}号,掉线后尝试重连");ReConnect();}}}}catch (Exception ex){ LogHelper.Error($"观察线程异常:{ex.Message}", ex);}finally{communicationobserve_timer.Enabled = true;}
}/// <summary>/// 最后一次重新连接的时间/// </summary>public DateTime LastConnectTime { get; set; }/// <summary>/// 距最后一次重连接的时长(秒)/// </summary>public double LastConnectLong{get{return (DateTime.Now - LastConnectTime).TotalSeconds;}}