// Dispose of WebBrowserPool
        public void Dispose()
        {
            if (_apartment == null)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }

            // cancel and wait for all pending tasks
            _cts.Cancel();
            var task = _apartment.Run(() => Task.WhenAll(_pendingTasks.ToArray()));

            try
            {
                task.Wait();
            }
            catch
            {
                if (!task.IsCanceled)
                {
                    throw;
                }
            }

            // dispose of WebBrowser objects
            _apartment.Run(() =>
            {
                while (_browsers.Any())
                {
                    _browsers.Dequeue().Dispose();
                }
            });

            _apartment.Dispose();
            _apartment = null;
        }
Пример #2
0
        // by Noseratio - http://stackoverflow.com/a/22262976/1768303

        // main logic
        static async Task ScrapSitesAsync(string[] urls, CancellationToken token)
        {
            using (var apartment = new MessageLoopApartment())
            {
                // create WebBrowser inside MessageLoopApartment
                var webBrowser = apartment.Invoke(() => new WebBrowser());
                try
                {
                    foreach (var url in urls)
                    {
                        Console.WriteLine("URL:\n" + url);

                        // cancel in 30s or when the main token is signalled
                        var navigationCts = CancellationTokenSource.CreateLinkedTokenSource(token);
                        navigationCts.CancelAfter((int)TimeSpan.FromSeconds(30).TotalMilliseconds);
                        var navigationToken = navigationCts.Token;

                        // run the navigation task inside MessageLoopApartment
                        string html = await apartment.Run(() =>
                                                          webBrowser.NavigateAsync(url, navigationToken), navigationToken);

                        Console.WriteLine("HTML:\n" + html);
                    }
                }
                finally
                {
                    // dispose of WebBrowser inside MessageLoopApartment
                    apartment.Invoke(() => webBrowser.Dispose());
                }
            }
        }
Пример #3
0
        CancellationTokenSource _cts;    // global cancellation (for Dispose)

        public WebBrowserPool(int maxParallel, CancellationToken token)
        {
            if (maxParallel < 1)
            {
                throw new ArgumentException("maxParallel");
            }

            _cts          = CancellationTokenSource.CreateLinkedTokenSource(token);
            _apartment    = new MessageLoopApartment();
            _semaphore    = new SemaphoreSlim(maxParallel);
            _browsers     = new Queue <WebBrowser>();
            _pendingTasks = new HashSet <Task>();

            // init the pool of WebBrowser objects
            _apartment.Invoke(() =>
            {
                while (--maxParallel >= 0)
                {
                    _browsers.Enqueue(new WebBrowser());
                }
            });
        }