/// <summary>
        /// Отслеживание события изменения данных
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void OnSubscriber_DataUpdated(object sender, DataUpdatedEventArgs <string> e)
        {
            string messageReceive = null;
            Target targetReader   = null;

            try
            {
                //targetReader = ManagerAllTargets.GetTargetReaderFromURL(CType(sender, Target).URLSendLocation)
                targetReader = (Target)sender;

                if (targetReader != null)
                {
                    targetReader.TimeStampTarget  = e.Data.TimeStamp.ToLocalTime().ToString();
                    targetReader.PipeServerStatus = e.Data.Quality;
                    messageReceive = e.Data.GetValue(); // содержат все сведения о данных

                    // получить только отличающиеся от старых данные
                    if (string.IsNullOrEmpty(messageReceive) || messageReceive == COMMAND_NOTHING)
                    {
                        return;
                    }

                    if (targetReader.LastCommand == e.Data.GetValue())
                    {
                        return;
                    }
                    else
                    {
                        // обновить поля target
                        targetReader.CommandValueReader = e.Data.GetValue();
                        targetReader.LastCommand        = e.Data.GetValue();
                        targetReader.ConfigReceive.LoadXMLfromString(messageReceive);
                        PopulateReader(targetReader);
                        RunTask(targetReader);
                    }
                }
            }
            catch (TimeoutException ex)
            {
                const string CAPTION = "Проблема с сетью:";
                string       text    = $"Получение данных коммандного обмена в <{nameof(OnSubscriber_DataUpdated)}>: ";
                if (targetReader != null)
                {
                    text += targetReader.URLReceiveLocation;
                    AppendMethod.Invoke(text + Environment.NewLine + Convert.ToString(ex), KEY_RICH_TEXT_SERVER, MessageBoxIcon.Error);
                }
                MessageBox.Show(text, CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                //RegistrationEventLog.EventLog_MSG_APPLICATION_MESSAGE(String.Format("<{0}> {1}", CAPTION, text))
            }
        }
        /// <summary>
        /// Делегат завершения асинхронной операции записи
        /// одинаков для типов NetworkVariableWriter(Of String) и NetworkVariableWriter(Of Boolean)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void Writer_WriteCompleted(object sender, WriteCompletedEventArgs e)
        {
            Target targetWriter = (Target)e.UserState;
            string errorText    = string.Empty;

            if (e.Error != null)
            {
                // обработать ошибку
                errorText = Convert.ToString(e.Error);
                AppendMethod.Invoke($"Ошибка при записи для: {targetWriter.URLSendLocation}{Environment.NewLine}{errorText}",
                                    targetWriter.IndexTab, MessageBoxIcon.Error);
            }

            if (targetWriter.IsControlCommadVisible)
            {
                targetWriter.UserControlCommandTarget.UpdateError(errorText);
            }
        }
        //    <MethodImplAttribute(MethodImplOptions.Synchronized)>
        /// <summary>
        /// Сформировать XML Команду Отправить к Target.
        /// Вызов из дежурного таймера по цепочке.
        /// </summary>
        /// <param name="targetWriter"></param>
        public void SendXMLCommand(Target targetWriter)
        {
            string strIndex = targetWriter.ConfigSend.GetRowValue(INDEX)[0];

            // поиск в листе приема
            if (targetWriter.ListCommandsReceive.Count > 0)
            {
                foreach (CommandForListViewItem itemCommand in targetWriter.ListCommandsReceive)
                {
                    if (itemCommand.IndexCommamd == strIndex)
                    {
                        itemCommand.Color = Color.Green;
                        // задача Найдена - отвечаем на запрос после выполнения, ее надо снять
                        if (targetWriter.IsControlCommadVisible)
                        {
                            targetWriter.UserControlCommandTarget.RefreshListCommandsReceive();
                        }
                        break;
                    }
                }
            }

            // отметить и послать задачу на выполнение
            targetWriter.ListCommandsSend.Add(new CommandForListViewItem(targetWriter.ConfigSend.GetRowValue(COMMAND_NAME)[0], targetWriter.ConfigSend.GetRowValue(COMMAND_DESCRIPTION)[0], targetWriter.ConfigSend.GetRowValue(COMMAND_COMMANDER_ID)[0], targetWriter.ConfigSend.GetRowValue(INDEX)[0]));

            //' для команды Stop нет необходимости в упаковке в XML, поэтому посылается простой текст
            //If targetWriter.ConfigSend.GetRowValue(NAME_COMMAND) = COMMAND_STOP Then
            //    commandValueWriter = COMMAND_STOP
            //Else
            string commandXMLValueWriter = targetWriter.ConfigSend.ToString();

            //End If

            targetWriter.SendText = commandXMLValueWriter;

            if (targetWriter.IsControlCommadVisible)
            {
                targetWriter.UserControlCommandTarget.UpdateSendTextBox(commandXMLValueWriter);
            }

            SendCommandConcreteTargetAsync(targetWriter, commandXMLValueWriter);
            AppendMethod.Invoke($"Послана команда: {targetWriter.ConfigSend.GetRowValue(COMMAND_DESCRIPTION)} Индекс:{targetWriter.ConfigSend.GetRowValue(INDEX)}", targetWriter.IndexTab, MessageBoxIcon.Information);
            //RegistrationEventLog.EventLog_AUDIT_SUCCESS($"Послана команда {commandValueWriter} на target: {targetWriter.HostName}")
        }
        /// <summary>
        /// Заполнить лист и таблицу Слушателя
        /// </summary>
        private void PopulateReader(Target targetReader)
        {
            string strIndex = targetReader.ConfigReceive.GetRowValue(INDEX)[0];

            // поиск в листе посылки для отметки команды, требующей подтверждения
            foreach (CommandForListViewItem itemCommand in targetReader.ListCommandsSend)
            {
                if (itemCommand.IndexCommamd == strIndex)
                {
                    itemCommand.Color = Color.Green;
                    // команда Найдена - пришел ответ о выполнении задачи, ее надо снять
                    if (targetReader.IsControlCommadVisible)
                    {
                        targetReader.UserControlCommandTarget.RefreshListCommandsSend();
                    }
                    break;
                }
            }

            // пришел запрос поставить задачу на выполнение
            targetReader.ListCommandsReceive.Add(new CommandForListViewItem(
                                                     targetReader.ConfigReceive.GetRowValue(COMMAND_NAME)[0],
                                                     targetReader.ConfigReceive.GetRowValue(COMMAND_DESCRIPTION)[0],
                                                     targetReader.ConfigReceive.GetRowValue(COMMAND_COMMANDER_ID)[0],
                                                     targetReader.ConfigReceive.GetRowValue(INDEX)[0]));

            if (targetReader.IsControlCommadVisible)
            {
                targetReader.UserControlCommandTarget.UpdateDataGridReceive();
                targetReader.UserControlCommandTarget.UpdateTimeStamp(targetReader.TimeStampTarget);
                targetReader.UserControlCommandTarget.UpdateStatusCommandPipeServer(targetReader.PipeServerStatus);
            }

            AppendMethod.Invoke($"Получена команда: {targetReader.ConfigReceive.GetRowValue(COMMAND_DESCRIPTION)[0]} индекс: {targetReader.ConfigReceive.GetRowValue(INDEX)[0]}{Environment.NewLine} от компьютера: {targetReader.HostName}",
                                KEY_RICH_TEXT_SERVER, MessageBoxIcon.Information);

            //RegistrationEventLog.EventLog_AUDIT_SUCCESS($"Получена команда {readValue} от компьютера: {targetReader.HostName}")
        }