private void Complete(object sender, DownloadDataCompletedEventArgs e)
        {
            WebClient client = (WebClient)sender;

            client.DownloadDataCompleted   -= Complete;
            client.DownloadProgressChanged -= Progress;

            DownloadTextHelper.Remove(this);

            if ((e != null) && e.Cancelled)
            {
                Logger.Add(string.Format("Загрузка книги '{0}' прервана.", AuthorText.Name));
            }
            else if ((e != null) && (e.Error != null))
            {
                Logger.Add(e.Error.StackTrace, false, true);
                Logger.Add(e.Error.Message, false, true);
                Logger.Add(string.Format("Ошибка при загрузке книги '{0}'.", AuthorText.Name), true, true);
            }

            if ((e != null) && (e.Error == null) && (!e.Cancelled))
            {
                Text = (e.Result != null) ? WEB.ConvertPage(e.Result) : null;
                if (Text != null)
                {
                    Text = PostProcess(Text);
                    if (!Directory.Exists(Path.GetDirectoryName(GetCachedFileName())))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(GetCachedFileName()));
                    }

                    // надо проверить разницу с предыдущим текстом
                    // для этого ищем предыдущий файл и сравниваем с ним, результат пишем в отдельный файл
                    #region Вычисление изменений в тексте файла

                    string CachedFileName = Path.GetFileNameWithoutExtension(GetCachedFileName());
                    // делаем так, потому что имя файла может поменяться. Мы ориентируемся на последний вариант в предположении,
                    // что автор обновляет проду, а не перезаливает с новым именем
                    // убираем штамп времени
                    string[] name_parts = CachedFileName.Split(".".ToCharArray());
                    if (name_parts.Length > 1)
                    {
                        string CachedFileNameWithoutTimeMask = "";
                        for (int i = 0; i < name_parts.Length - 1; i++)
                        {
                            CachedFileNameWithoutTimeMask = CachedFileNameWithoutTimeMask +
                                                            ((CachedFileNameWithoutTimeMask == "") ? name_parts[i] : "." + name_parts[i]);
                        }
                        CachedFileNameWithoutTimeMask = CachedFileNameWithoutTimeMask + ".";
                        // берем последний закачанный файл
                        var files = from f in Directory.GetFiles(Path.GetDirectoryName(GetCachedFileName()))
                                    where Path.GetFileName(f).ToLower().StartsWith(CachedFileNameWithoutTimeMask.ToLower()) &&
                                    Path.GetFileName(f).ToLower().EndsWith(".shtml")
                                    orderby f
                                    select f;
                        string last_file = "";
                        if (files.Count() > 0)
                        {
                            last_file = files.Last();
                        }

                        // если такой есть, то проведем сравнение
                        #region код вычисления различий
                        // если текст больше 150 кило - небудем находить различия, ибо медленно
                        if (Text.Length < 150 * 1024)
                        {
                            if (!string.IsNullOrEmpty(last_file))
                            {
                                // засунем вычисления в отдельный поток, так как это медленная операция
                                System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
                                bw.DoWork += (o, e1) =>
                                {
                                    Logger.Add(string.Format("Нахождение различий в обновлении книги '{0}'.", AuthorText.Name));
                                    Helpers.HtmlDiff diff      = new Helpers.HtmlDiff(File.ReadAllText(last_file, Encoding.GetEncoding(1251)), Text);
                                    string           diff_file = "";
                                    try
                                    {
                                        diff_file = diff.Build();
                                    }
                                    catch
                                    { }
                                    if (!string.IsNullOrEmpty(diff_file))
                                    {
                                        diff_file = diff_file.Replace("<head>", "<head><STYLE type=\"text/css\">table {border:1px solid #d9d9d9;} td {border:1px solid #d9d9d9; padding:3px;} ins {background-color: #00542E;text-decoration:inherit;} del {color: #999;	background-color:#FEC8C8;} ins.mod { background-color: #FFE1AC; }</STYLE>");
                                        File.WriteAllText(
                                            Path.Combine(Path.GetDirectoryName(GetCachedFileName()), CachedFileName + "_diff.shtml"),
                                            diff_file, Encoding.GetEncoding(1251));
                                        AuthorText.UpdateHasDiff(_author);
                                    }
                                    Logger.Add(string.Format("Файл различий в обновлении книги '{0}' сформирован.", AuthorText.Name));
                                };
                                bw.RunWorkerAsync();
                            }
                        }
                        else
                        {
                            Logger.Add(string.Format("Нахождение различий в обновлении книги '{0}' не будет произведено, оазмер превышает 150кб.", AuthorText.Name));
                        }
                        #endregion
                    }


                    #endregion


                    File.WriteAllText(GetCachedFileName(), Text, Encoding.GetEncoding(1251));
                    Logger.Add(string.Format("Книга '{0}' закачана.", AuthorText.Name));
                }
            }
            if (DownloadTextComplete != null)
            {
                DownloadTextComplete(this, e);
            }
        }