예제 #1
0
        /// <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);
        }