public WebSocketClient([NotNull] WebSocketListenerOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            if (options.Standards.Count == 0)
            {
                throw new ArgumentException("Empty list of WebSocket standards.", nameof(options));
            }

            options.CheckCoherence();
            this.options = options.Clone();
            this.options.SetUsed(true);

            if (this.options.NegotiationTimeout > TimeSpan.Zero)
            {
                this.negotiationsTimeoutQueue = new CancellationQueue(this.options.NegotiationTimeout);
            }
            if (this.options.PingMode != PingMode.Manual)
            {
                this.pingQueue = new PingQueue(options.PingInterval);
            }

            this.log        = this.options.Logger;
            this.closeEvent = new AsyncConditionSource(isSet: true)
            {
                ContinueOnCapturedContext = false
            };
            this.workCancellationSource = new CancellationTokenSource();
            this.pendingRequests        = new ConcurrentDictionary <WebSocketHandshake, Task <WebSocket> >();

            if (this.options.BufferManager == null)
            {
                this.options.BufferManager = BufferManager.CreateBufferManager(100, this.options.SendBufferSize * 2); // create small buffer pool if not configured
            }
            if (this.options.CertificateValidationHandler == null)
            {
                this.options.CertificateValidationHandler = this.ValidateRemoteCertificate;
            }
        }
        public void SubscribeAndDispatch(int milliseconds)
        {
            var sw            = Stopwatch.StartNew();
            var timedQueue    = new CancellationQueue(TimeSpan.FromMilliseconds(milliseconds / 2.0));
            var subscriptions = 0;
            var hits          = 0;

            while (sw.ElapsedMilliseconds < milliseconds)
            {
                timedQueue.GetSubscriptionList().Token.Register(() => Interlocked.Increment(ref hits));
                subscriptions++;
                Thread.Sleep(10);
            }

            sw.Reset();
            while (sw.ElapsedMilliseconds < milliseconds && subscriptions != hits)
            {
                Thread.Sleep(10);
            }

            this.logger.Debug($"[TEST] subscriptions: {subscriptions}, hits: {hits}.");

            Assert.Equal(subscriptions, hits);
        }