private void Crawler_ProcessPageCrawlCompleted(object sender, PageCrawlCompletedArgs e)
        {
            PageToCrawl      pageToCrawl = e.CrawledPage;
            TestResultDetail item        = e.CrawledPage.PageBag.Item;

            lock (mainLock)
            {
                rootMeanResponseTime += item.MeanResponseTime;
                if (item.MinResponseTime < rootMinResponseTime)
                {
                    rootMinResponseTime = item.MinResponseTime;
                }
                if (item.MaxResponseTime > rootMaxResponseTime)
                {
                    rootMaxResponseTime = item.MaxResponseTime;
                }
                ++numberOfPagesCrawled;
            }
            if (!processedPages.ContainsKey(item.Uri))
            {
                resultDetails.Add(item);
                processedPages.TryAdd(item.Uri, 0);
                PageTestingCompleted?.Invoke(this, new PageTestingCompletedArgs(item));
            }
        }
        public void Start(TestResult root)
        {
            using (HttpClient client = new HttpClient())
            {
                var testBlock = new ActionBlock <TestResultDetail>(async item =>
                {
                    Stopwatch timer = new Stopwatch();

                    double mean = 0;

                    for (int i = 1; i <= NumberOfRecurrentRequests; ++i)
                    {
                        timer.Start();
                        await client.GetAsync(item.Uri);
                        timer.Stop();
                        long responseTime = timer.ElapsedMilliseconds;
                        timer.Reset();

                        if (i == 1)
                        {
                            ProcessFirstItem(item, responseTime);
                        }
                        else
                        {
                            ProcessItem(item, responseTime);
                        }
                        mean += responseTime / NumberOfRecurrentRequests;
                    }

                    item.MeanResponseTime = mean;
                    PageTestingCompleted?.Invoke(this, new PageTestingCompletedArgs(item));
                    lock (mainLock)
                    {
                        rootMeanResponseTime += item.MeanResponseTime;
                        if (item.MinResponseTime < rootMinResponseTime)
                        {
                            rootMinResponseTime = item.MinResponseTime;
                        }
                        if (item.MaxResponseTime > rootMaxResponseTime)
                        {
                            rootMaxResponseTime = item.MaxResponseTime;
                        }
                    }
                },
                                                                   new ExecutionDataflowBlockOptions()
                {
                    MaxDegreeOfParallelism = MaxConcurrentThreads
                });

                foreach (var item in root.TestResultDetails)
                {
                    testBlock.Post(item);
                }

                testBlock.Complete();

                root.TestDate = DateTime.Now;
                root.Status   = 1;
                RepositoryUpdateRequested?.Invoke(this, new TestResultArgs(root));
                TestStarted?.Invoke(this, new TestResultArgs(root));

                testBlock.Completion.Wait();
            }

            root.MinResponseTime  = rootMinResponseTime;
            root.MaxResponseTime  = rootMaxResponseTime;
            root.MeanResponseTime = rootMeanResponseTime / root.TestResultDetails.Count;
            root.Status           = 0;

            TestFinished?.Invoke(this, new TestResultArgs(root));
            RepositoryUpdateRequested?.Invoke(this, new TestResultArgs(root));
        }