如何创建全局可用的 WebClient 对象
How to create a globally available WebClient object
我有一个 windows 形式的下载程序,可以下载一堆 URL 的 html 源代码,并提取更多 URL 并下载那些东西。我正在使用
using(WebClient client = new WebClient())
{
// Do download stuff here...
}
但是 .NET 内存探查器显示严重的内存泄漏,因为很多对象已被垃圾回收但未被处置或被处置但未被垃圾回收。听起来很奇怪,但我的程序有内存泄漏。
要了解我的程序,请考虑以下代码:
private void PreprocessURLs(List<string> URLs)
{
using(WebClient client = new WebClient())
{
// Download first batch of html source code and put in a List<string> property
}
}
private void ProcessURLs(List<string> URLs)
{
using(WebClient client = new WebClient())
{
// Download more stuff and save them
}
}
等等。这不是实际的程序,但我想向您展示的是,如何创建一个 "globally" 可用的 WebClient object/instance,这样我就不会创建一堆客户端对象?我想重复使用它。我怀疑这是导致内存泄漏的原因(也许还有其他原因)。也许我错了,因为我从来没有创建过一个程序,其中的任务可能会导致内存泄漏。
编辑:根据 tlemster 的建议,我创建了 WebClient 的静态实例,但这会导致 I/O 错误,因为不支持并发 I/O (DownloadFileAsync())。
EDIT1:这是我的下载方法,它完成主要工作并通过这样做阻止我的 UI 线程。因此我相信内存泄漏来自这个函数。
private void Download()
{
var stopwatch = new Stopwatch();
string bla;
string chapterName;
string bla1;
string chapterNumber;
List<Tuple<string, int>> temp = new List<Tuple<string, int>>();
// Contains all URLs from preprocessing
foreach (var chapter in Chapters)
{
bla = chapter.Item2;
chapterName = ReplaceSpecialChars(bla);
bla1 = chapter.Item3;
chapterNumber = ReplaceSpecialChars(bla1);
// Skip this chapter if it already exists based on chapter name
if (Directory.Exists(string.Format("{0}/{1} - {2}", chapter.Item4, chapterNumber, chapterName)))
{
continue;
}
else
{
Directory.CreateDirectory(string.Format("{0}/{1} - {2}", chapter.Item4, chapterNumber, chapterName));
}
// Process each chapter and extract other URLs
foreach (var item in GetPagesLink(chapter.Item1))
{
// Add the extracted URLs to a list for download further down
temp.Add(new Tuple<string, int>(GetImageLink(item.Item1), item.Item2));
}
stopwatch.Start();
// The download of the files I want after processing it two times
foreach (var img in temp)
{
// A static WebClient does not work because DownloadFileAsync() does not support concurrent I/O
// Atm should not matter because this whole thing is not async anyway...
using (WebClient webClient = new WebClient())
{
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
webClient.DownloadFileAsync(new Uri(img.Item1), string.Format("{0}/{1} - {2}/{3}.jpg", chapter.Item4, chapterNumber, chapterName, img.Item2)); // TODO: Find image type and replace hardcoded jpg
System.Threading.Thread.Sleep(150);
}
}
stopwatch.Stop();
temp.Clear();
txtDebug.AppendText("Finished chapter " + chapter.Item3 + " : " + stopwatch.ElapsedMilliseconds + "\r\n");
stopwatch.Reset();
}
Chapters.Clear();
}
将创建的 WebClient 存储在静态字段中,只要您的程序 运行 或直到您手动删除它,它就会使实例保持活动状态。
我有一个 windows 形式的下载程序,可以下载一堆 URL 的 html 源代码,并提取更多 URL 并下载那些东西。我正在使用
using(WebClient client = new WebClient())
{
// Do download stuff here...
}
但是 .NET 内存探查器显示严重的内存泄漏,因为很多对象已被垃圾回收但未被处置或被处置但未被垃圾回收。听起来很奇怪,但我的程序有内存泄漏。
要了解我的程序,请考虑以下代码:
private void PreprocessURLs(List<string> URLs)
{
using(WebClient client = new WebClient())
{
// Download first batch of html source code and put in a List<string> property
}
}
private void ProcessURLs(List<string> URLs)
{
using(WebClient client = new WebClient())
{
// Download more stuff and save them
}
}
等等。这不是实际的程序,但我想向您展示的是,如何创建一个 "globally" 可用的 WebClient object/instance,这样我就不会创建一堆客户端对象?我想重复使用它。我怀疑这是导致内存泄漏的原因(也许还有其他原因)。也许我错了,因为我从来没有创建过一个程序,其中的任务可能会导致内存泄漏。
编辑:根据 tlemster 的建议,我创建了 WebClient 的静态实例,但这会导致 I/O 错误,因为不支持并发 I/O (DownloadFileAsync())。
EDIT1:这是我的下载方法,它完成主要工作并通过这样做阻止我的 UI 线程。因此我相信内存泄漏来自这个函数。
private void Download()
{
var stopwatch = new Stopwatch();
string bla;
string chapterName;
string bla1;
string chapterNumber;
List<Tuple<string, int>> temp = new List<Tuple<string, int>>();
// Contains all URLs from preprocessing
foreach (var chapter in Chapters)
{
bla = chapter.Item2;
chapterName = ReplaceSpecialChars(bla);
bla1 = chapter.Item3;
chapterNumber = ReplaceSpecialChars(bla1);
// Skip this chapter if it already exists based on chapter name
if (Directory.Exists(string.Format("{0}/{1} - {2}", chapter.Item4, chapterNumber, chapterName)))
{
continue;
}
else
{
Directory.CreateDirectory(string.Format("{0}/{1} - {2}", chapter.Item4, chapterNumber, chapterName));
}
// Process each chapter and extract other URLs
foreach (var item in GetPagesLink(chapter.Item1))
{
// Add the extracted URLs to a list for download further down
temp.Add(new Tuple<string, int>(GetImageLink(item.Item1), item.Item2));
}
stopwatch.Start();
// The download of the files I want after processing it two times
foreach (var img in temp)
{
// A static WebClient does not work because DownloadFileAsync() does not support concurrent I/O
// Atm should not matter because this whole thing is not async anyway...
using (WebClient webClient = new WebClient())
{
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
webClient.DownloadFileAsync(new Uri(img.Item1), string.Format("{0}/{1} - {2}/{3}.jpg", chapter.Item4, chapterNumber, chapterName, img.Item2)); // TODO: Find image type and replace hardcoded jpg
System.Threading.Thread.Sleep(150);
}
}
stopwatch.Stop();
temp.Clear();
txtDebug.AppendText("Finished chapter " + chapter.Item3 + " : " + stopwatch.ElapsedMilliseconds + "\r\n");
stopwatch.Reset();
}
Chapters.Clear();
}
将创建的 WebClient 存储在静态字段中,只要您的程序 运行 或直到您手动删除它,它就会使实例保持活动状态。