public void DownloadChapter(object s)
        {
            var cha = (BookIndexViewModel.DownloadTask) s;

            var downloader = new HttpContentDownloader();
            downloader.Download(cha.TaskChapter.ChapterUri, ar =>
                                                                {
                                                                    //At this step, we can get the index page in the search engine 
                                                                    var state = (RequestState) ar.AsyncState;
                                                                    var response =
                                                                        (HttpWebResponse)
                                                                        state.Request.EndGetResponse(ar);
                                                                    response.GetResponseStream();

                                                                    var parser = new WebSiteBookContentPageParser();
                                                                    parser.Parse(response.GetResponseStream(),
                                                                                 cha.TaskChapter);
                                                                    CommonModels.TestChapter = chapter;
                                                                });
        }
        /// <summary>
        /// Download single chapter, should be active from the ChapterView Page
        /// </summary>
        /// <param name="chapter"></param>
        /// <param name="callback"></param>
        public void DownloadSingleChapter(Chapter chapter, Action callback)
        {
            var downloader = new HttpContentDownloader();
            downloader.Download(chapter.ChapterUri, ar =>
            {
                try
                {
                    //At this step, we can get the index page in the search engine 
                    var state = (RequestState)ar.AsyncState;
                    state.stopTimer = true;
                    var response = (HttpWebResponse)state.Request.EndGetResponse(ar);
                    response.GetResponseStream();

                    var parser = new WebSiteBookContentPageParser();
                    parser.ParsingCompleted += ChapterContentParsingCompleted;

                    chapter.Downloaded = true;
                    parser.Parse(response.GetResponseStream(), chapter);

                    if (callback != null)
                    {
                        callback();
                    }
                }
                catch (WebException e)
                {
                    //TODO need to recover from exception
                    ExceptionHandler.HandleException(e);
                }
            });
        }
        public void GetBookSiteBookIndexPageLink(Book book)
        {
            var downloader = new HttpContentDownloader();
            try
            {
                downloader.Download(book.IndexPage,
                    ar =>
                    {
                        try
                        {
                            //At this step, we can get the index page in the search engine 
                            var state = (RequestState)ar.AsyncState;
                            var response = (HttpWebResponse)state.Request.EndGetResponse(ar);
                            response.GetResponseStream();

                            book.RootUrl = UrlHelper.GetRootUrlString(response.ResponseUri);
                            var parser = new WebSiteBookContentPageParser();
                            parser.Parse(response.GetResponseStream(), book);

                            DownloadAndParseWebSiteBookIndexPage(book);

                        }
                        catch (WebException e)
                        {
                            if (e.Status == WebExceptionStatus.RequestCanceled)
                            {
                                throw new TimeoutException(String.Format("连接{0}超时", book.WebSite.WebSiteName));
                            }
                        }

                    });
            }
            catch (WebException we)
            {
                ExceptionHandler.HandleException(we);
            }
        }
        public void DownloadChapter(object s)
        {
            var cha = (DownloadTask)s;
            var downloader = new HttpContentDownloader();
            DownloaderList.Add(downloader);
            downloader.Download(cha.TaskChapter.ChapterUri, ar =>
            {
                try
                {
                    //At this step, we can get the index page in the search engine 
                    var state = (RequestState)ar.AsyncState;
                    state.stopTimer = true;
                    var response = (HttpWebResponse)state.Request.EndGetResponse(ar);
                    response.GetResponseStream();

                    var parser = new WebSiteBookContentPageParser();
                    parser.Parse(response.GetResponseStream(), cha.TaskChapter);

                    lock (_thisLock)
                    {
                        _batchCompleteCount++;
                    }

                    if (_batchCompleteCount == cha.BatchCount)
                    {
                        _batchCompleteCount = 0;
                        ((ManualResetEvent) cha.ResetEvent).Set();
                    }

                }catch (WebException e)
                {
                    ProgressIndicatorHelper.StopProgressIndicator();
                    if (e.Status == WebExceptionStatus.RequestCanceled)
                    {
                        throw new TimeoutException(String.Format("连接{0}超时", cha.TaskChapter.Book.WebSite.WebSiteName));
                    }
                    //TODO need to recover from exception
                    ExceptionHandler.HandleException(e);
                }
            });
        }