public DotNetBrowserService(
            [Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider,
            IEventAggregator eventAggregator)
        {
            _serviceProvider = serviceProvider;
            _eventAggregator = eventAggregator;

            try {
                _messageQueue     = new BlockingCollection <string>(new ConcurrentQueue <string>());
                _manualResetEvent = new ManualResetEvent(false);
                _disposables      = new List <IDisposable>()
                {
                    _eventAggregator.GetEvent <WebviewDidInitializeEvent>().Subscribe(_ => {
                        Log.Debug($"{nameof(WebviewDidInitializeEvent)} Message QueueCount={QueueCount}");
                        _manualResetEvent.Set();

                        _disposable = _eventAggregator.GetEvent <SessionReadyEvent>().Subscribe(nested => {
                            Log.Debug($"{nameof(SessionReadyEvent)} Message QueueCount={QueueCount}");
                            if (!_manualResetEvent.WaitOne(0))
                            {
                                _manualResetEvent.Set();
                            }
                        });
                    }),
                    _eventAggregator.GetEvent <SessionLogoutEvent>().Subscribe(_ => {
                        Log.Debug($"{nameof(SessionLogoutEvent)} Message QueueCount={QueueCount}");
                        _queueTokenSource?.Cancel();
                        _messageQueue.ClearAll();
                        _manualResetEvent.Reset();
                    })
                };

                //https://stackoverflow.com/questions/9106419/how-to-cancel-getconsumingenumerable-on-blockingcollection
                _processorTokenSource = new CancellationTokenSource();
                var processorToken = _processorTokenSource.Token;

                _processor = System.Threading.Tasks.Task.Factory.StartNew(() => {
                    try {
                        while (_manualResetEvent.WaitOne())
                        {
                            if (processorToken.IsCancellationRequested)
                            {
                                break;
                            }

                            _queueTokenSource = new CancellationTokenSource();
                            var queueToken    = _queueTokenSource.Token;
                            try {
                                foreach (var value in _messageQueue.GetConsumingEnumerable(_queueTokenSource.Token))
                                {
                                    if (queueToken.IsCancellationRequested)
                                    {
                                        break;
                                    }

                                    if (_messageQueue.Count > QueueLimit)
                                    {
                                        _messageQueue.ClearAll();
                                        _manualResetEvent.Reset();
#pragma warning disable VSTHRD010
                                        ReloadWebView();
#pragma warning restore VSTHRD010
                                        break;
                                    }

                                    Send(value);
                                }
                            }
                            catch (OperationCanceledException ex) {
                                //no need to pass the error, this exception is expected
                                Log.Verbose(ex.Message);
                            }
                            catch (Exception ex) {
                                Log.Error(ex, ex.Message);
                            }
                        }
                    }
                    catch (Exception ex) {
                        Log.Error(ex.Message);
                    }
                }, processorToken, TaskCreationOptions.None, TaskScheduler.Default);
            }
            catch (Exception ex) {
                Log.Fatal(ex, nameof(DotNetBrowserService));
            }
        }