/// <summary>Ensure <paramref name="process"/> is actually running.</summary>
        private async Task <bool> EnsureRunningAsync(ProcessAsync process, CancellationToken token)
        {
            int i = 0;

            while (true)
            {
                i++;

                bool isRunning = await TcpConnectionFactory.IsTorRunningAsync().ConfigureAwait(false);

                if (isRunning)
                {
                    return(true);
                }

                if (process.HasExited)
                {
                    Logger.LogError("Tor process failed to start!");
                    return(false);
                }

                const int MaxAttempts = 25;

                if (i >= MaxAttempts)
                {
                    Logger.LogError($"All {MaxAttempts} attempts to connect to Tor failed.");
                    return(false);
                }

                // Wait 250 milliseconds between attempts.
                await Task.Delay(250, token).ConfigureAwait(false);
            }
        }
        /// <summary>Starts Tor process if it is not running already.</summary>
        /// <exception cref="OperationCanceledException"/>
        public async Task <bool> StartAsync(CancellationToken token = default)
        {
            ThrowIfDisposed();

            ProcessAsync?    process       = null;
            TorControlClient?controlClient = null;

            try
            {
                // Is Tor already running? Either our Tor process from previous Wasabi Wallet run or possibly user's own Tor.
                bool isAlreadyRunning = await TcpConnectionFactory.IsTorRunningAsync().ConfigureAwait(false);

                if (isAlreadyRunning)
                {
                    Logger.LogInfo($"Tor is already running on {Settings.SocksEndpoint.Address}:{Settings.SocksEndpoint.Port}.");
                    TorControlClient = await InitTorControlAsync(token).ConfigureAwait(false);

                    return(true);
                }

                string arguments = Settings.GetCmdArguments();
                process = StartProcess(arguments);

                bool isRunning = await EnsureRunningAsync(process, token).ConfigureAwait(false);

                if (!isRunning)
                {
                    return(false);
                }

                controlClient = await InitTorControlAsync(token).ConfigureAwait(false);

                Logger.LogInfo("Tor is running.");

                // Only now we know that Tor process is fully started.
                TorProcess       = process;
                TorControlClient = controlClient;
                controlClient    = null;
                process          = null;

                return(true);
            }
            catch (OperationCanceledException ex)
            {
                Logger.LogDebug("User canceled operation.", ex);
                throw;
            }
            catch (Exception ex)
            {
                Logger.LogError("Could not automatically start Tor. Try running Tor manually.", ex);
            }
            finally
            {
                if (controlClient is not null)
                {
                    await controlClient.DisposeAsync().ConfigureAwait(false);
                }

                process?.Dispose();
            }

            return(false);
        }