/// <summary> /// Задача (пере)открытия сокета /// </summary> private void Connect() { Task.Factory.StartNew(() => { var cancellationToken = cancellationTokenSource.Token; Thread.CurrentThread.Name = "CQGC_CONN"; // количество попыток коделчения нужно ограничивать int attempts = 0, attemptsLimit = 5; var major = (int)ProtocolVersionMajor.PROTOCOL_VERSION_MAJOR; var minor = (int)ProtocolVersionMinor.PROTOCOL_VERSION_MINOR; Log.Info().Print($"Using CQG Continuum protocol v{major}.{minor}"); while (!cancellationToken.IsCancellationRequested) { var shouldSleep = false; var shouldWait = false; // если была ошибка авторизации, то мы не можем дальше продолжать попытки реконнекта if (connectionStatus == ConnectionStatus.Terminated) { Log.Error().Print( "Cancelling reconnection task", LogFields.ConnectionStatus(connectionStatus), LogFields.Login(settings?.Username) ); break; } using (socketLock.Lock()) { if (socket == null) { if (++attempts > attemptsLimit) { Log.Error().Print("CQG transport was stopped due to relogon attempts limit", LogFields.Login(settings?.Username)); break; } CreateAndOpenSocket(); shouldSleep = true; } else { switch (socket.State) { case WebSocketState.Open: shouldWait = true; break; case WebSocketState.None: case WebSocketState.Closed: case WebSocketState.Closing: case WebSocketState.Connecting: default: break; } } } if (shouldWait) { Log.Debug().Print("Waiting for task cancellation or connection error to reconnect"); // замораживаем поток в ожидании отмены всех задач или разрыва соединения сокета if (WaitContinueOrCancel(cancellationToken, socketErrorEvent)) { Log.Debug().Print( "Task has been cancelled, thread exited", LogFields.ConnectionStatus(connectionStatus), LogFields.State(socket?.State), LogFields.Login(settings?.Username) ); return; } } if (shouldSleep) { Log.Debug().Print( $"Sleep for 10 sec", LogFields.ConnectionStatus(connectionStatus), LogFields.State(socket?.State), LogFields.Login(settings?.Username) ); Thread.Sleep(10000); } } Log.Debug().Print( $"Task completed, thread exited", LogFields.ConnectionStatus(connectionStatus), LogFields.State(socket?.State), LogFields.Login(settings?.Username) ); }, TaskCreationOptions.LongRunning); }