public override void SendThreading() { LastSendTime = DateTime.Now; Telegram tel = null; while (Thread.CurrentThread.ThreadState == ThreadState.Background) { try { lock (_lockSendTelegram) tel = SendTelegrams.FirstOrDefault(prop => prop.CommSendStatus < Telegram.CommSendStatusEnum.Ack); if (tel != null) { if (INotifyTelegramCallBack == null) { throw new TelegramException(String.Format("Callback for {0} is not registered.", Name)); } INotifyTelegramCallBack?.Invoke(tel); Log?.AddLog(Log.Severity.EVENT, Name, "MFCSCommunicator.SendThreading Telegram written", tel.ToString()); do { WaitHandle.WaitAny(new WaitHandle[] { _newSendNotifyTelegram }, (int)SendTimeOut.TotalMilliseconds, true); // TODO it is a long time Telegram tel1 = null; lock (_lockSendNotifyTelegram) tel1 = SendNotifyTelegrams.FirstOrDefault(); if (tel1 == null) { if (!INotifyLongWait.Invoke(tel)) { throw new TelegramException("Long wait without knowledge of service communicator..."); } } if (tel1 != null) { // check if both telegrams are completely identical tel.Sequence = tel1.Sequence; tel1.CommSendStatus = tel.CommSendStatus; tel.SetCRC(); tel1.SetCRC(); if (tel.CRC != tel1.CRC) { Log?.AddLog(Log.Severity.EXCEPTION, Name, "MFCSCommunicator.SendThreadind:tel={0}", tel.ToString()); Log?.AddLog(Log.Severity.EXCEPTION, Name, "MFCSCommunicator.SendThreadind:tel1={0}", tel1.ToString()); throw new TelegramException(String.Format("SendNotify telegram CRC does not match ({0},{1})", tel.CRC, tel1.CRC)); } lock (_lockSendTelegram) SendTelegrams.Remove(tel); lock (_lockSendNotifyTelegram) SendNotifyTelegrams.Remove(tel1); Log?.AddLog(Log.Severity.EVENT, Name, "MFCSCommunicator.SendThreading send phase finished", tel.ToString()); tel = null; } } while (tel != null); } else { WaitHandle.WaitAny(new WaitHandle[] { _newSendTelegram, _newSendNotifyTelegram }, 100, true); } } catch (TelegramException ex) { Log?.AddLog(Log.Severity.EXCEPTION, Name, "MFCSCommunicator.SendThread::TelegramException", ex.Message); Thread.Sleep(1000); } }
// Main thread for sending telegrams private void SendThreading() { TelegramACK telAck = null; try { if (SimulateMFCS) { SendListener = new TcpListener(SendIPEndPoint); Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThreading", SendIPEndPoint.ToString()); SendListener.Start(); } lock (_lockSendTelegram) { SendTelegrams.RemoveAll(p => p.CommSendStatus >= Telegram.CommSendStatusEnum.Ack); } LastSendTime = DateTime.Now; while (Thread.CurrentThread.ThreadState == ThreadState.Background) { try { Telegram tel = null; lock (_lockSendTelegram) tel = SendTelegrams.FirstOrDefault(prop => prop.CommSendStatus < Telegram.CommSendStatusEnum.Ack); if (DateTime.Now - LastSendTime > SendTimeOut) { InitSendSocket(); if (tel != null) { tel.CommSendStatus = Telegram.CommSendStatusEnum.None; } LastSendTime = DateTime.Now; Retry = 0; Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThread", "Send timeout, SendSocket reinitialized!"); } else if (DateTime.Now - LastSendTime > KeepALifeTime && tel == null) { Telegram tRes = null; lock (_lockSendTelegram) tRes = SendTelegrams.FirstOrDefault(prop => prop.CommSendStatus < Telegram.CommSendStatusEnum.Ack); if (tRes == null) { if (KeepALifeTelegram != null) { Telegram t = Activator.CreateInstance(KeepALifeTelegram.GetType()) as Telegram; t.Sender = MFCS_ID; t.Receiver = PLC_ID; t.Build(); AddSendTelegram(t); Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThread", String.Format("Adding KeepALife telegram")); } } } else if (!SendSocket.Connected) { InitSendSocket(); ConnectSendPartner(); } else if (tel != null) { switch (tel.CommSendStatus) { case (Telegram.CommSendStatusEnum.None): tel.Sequence = Sequence; tel.Build(); // Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThread", String.Format("Start sending {0}", tel.ToString())); SendSocket.Send(tel.ByteBuffer, tel.Length, SocketFlags.None); Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThread", String.Format("Sended {0}", tel.ToString())); tel.CommSendStatus = Telegram.CommSendStatusEnum.WaitACK; telAck = new TelegramACK(); SendTime = DateTime.Now; break; case (Telegram.CommSendStatusEnum.WaitACK): int numRead = 0; do { numRead += SendSocket.Receive(telAck.ByteBuffer, numRead, telAck.ByteBuffer.Length - numRead, SocketFlags.None); } while (numRead < telAck.ByteBuffer.Length); telAck.ReadBuffer(); Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThread", String.Format("Received ACK {0}", telAck.ToString())); if (telAck.Validate() && telAck.Sequence == tel.Sequence) { tel.CommSendStatus = Telegram.CommSendStatusEnum.Ack; LastSendTime = DateTime.Now; Retry = 0; if (Sequence < 99) { Sequence++; } else { Sequence = 0; } Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThreading", String.Format("Send Finished : {0}", tel.ToString())); NotifySend(tel); } else { // tel.CommSendStatus = Telegram.CommSendStatusEnum.None; Retry++; Log.AddLog(Log.Severity.EVENT, Name, "Communication.SendThreading", String.Format("Retry increased - {0}", Retry)); } break; default: break; } } else { Thread.Sleep(100); } } catch (SocketException ex) { Log.AddLog(Log.Severity.EXCEPTION, Name, "Communication.SendThread::SocketException", ex.Message); Thread.Sleep(1000); } } catch (TelegramException ex) { Log.AddLog(Log.Severity.EXCEPTION, Name, "Communication.SendThread::TelegramException", ex.Message); Thread.Sleep(1000); } catch (ThreadAbortException ex) { Log.AddLog(Log.Severity.EXCEPTION, Name, "Communication.RcvThreading::Communication", ex.Message); return; } catch (CommunicationException ex) { Log.AddLog(Log.Severity.EXCEPTION, Name, "Communication.SendThread::CommunicationException", ex.Message); Thread.Sleep(1000); } }