我正在用 C# 编写一个应用程序,该应用程序循环浏览维基百科本地数据库副本的文章。我使用一堆正则表达式在这些文章中找到正确的信息,启动一个线程来获取每篇文章的图像,保存信息并转到下一篇文章。
我需要使用代理列表来下载这些图像,以免被谷歌禁止。由于代理可能很慢,我使用线程进行并行下载。
如果我不使用线程,则应用程序工作正常,但需要一段时间才能获取所有信息。
如果我使用线程,应用程序将一直工作,直到它使用大约 500 个线程,然后我得到一个 OutOfMemory 异常。
问题是它只使用了大约 300Mo 的 RAM,因此它不会使用可用总内存 (8Go) 和分配给单个 32 位应用程序的内存的所有内存。
每个应用程序有线程限制吗?
编辑:
这是下载海报的代码(从 getPosterAsc() 开始)。
string ddlValue = "";
private void tryDownload(object obj)
{
WebClient webClientProxy = new WebClient();
Tuple<WebProxy, int> proxy = (Tuple<WebProxy, int>)((object[])obj)[0];
if (proxy != null)
webClientProxy.Proxy = proxy.Item1;
try
{
ddlValue = webClientProxy.DownloadString((string)((object[])obj)[1]);
}
catch (Exception ex) {
ddlValue = "";
Console.WriteLine("trydownload:" + ex.Message);
}
webClientProxy.Dispose();
}
public void getPoster(object options = null)
{
if (options == null)
options = new object[2] { toSave, false };
if (!AppVar.debugMode && AppVar.getImages && this.getImage)
{
if (this.original_name != "" && !this.ambName && this.suitable)
{
Log.CountImgInc();
MatchCollection MatchList;
string basic_options = "";
string value = "";
WebClient webClient = new WebClient();
Regex reg;
bool found = false;
if (original_name.Split(' ').Length > 1) image_options = "";
if (!found)
{
bool succes = false;
int countTry = 0;
while (!succes)
{
Tuple<WebProxy, int> proxy = null;
if (countTry != 5)
proxy = Proxy.getProxy();
try
{
Thread t = new Thread(tryDownload);
if (!(bool)((object[])options)[1])
t.Start(new object[] { proxy, @"http://www.google.com/search?as_st=y&tbm=isch&as_q=" + image_options + "+" + basic_options + "+" + image_options_before + "%22" + simplify(original_name) + "%22+" + " OR %22" + original_name + "%22+" + image_options_after + this.image_format });
else
t.Start(new object[] { proxy, @"http://www.google.com/search?as_st=y&tbm=isch&as_q=" + image_options + "+" + basic_options + "+" + image_options_before + "%22" + simplify(original_name) + "%22+" + " OR %22" + original_name + "%22+" + image_options_after + "&biw=1218&bih=927&tbs=isz:ex,iszw:758,iszh:140,ift:jpg&tbm=isch&source=lnt&sa=X&ei=kuG7T6qaOYKr-gafsOHNCg&ved=0CIwBEKcFKAE" });
if (!t.Join(40000))
{
Proxy.badProxy(proxy.Item1.Address.Host, proxy.Item1.Address.Port);
continue;
}
else
{
value = ddlValue;
if (value != "")
succes = true;
else
Proxy.badProxy(proxy.Item1.Address.Host, proxy.Item1.Address.Port);
}
}
catch (Exception ex)
{
if (proxy != null)
Proxy.badProxy(proxy.Item1.Address.Host, proxy.Item1.Address.Port);
}
countTry++;
}
reg = new Regex(@"imgurl\=(.*?)&imgrefurl", RegexOptions.IgnoreCase);
MatchList = reg.Matches(value);
if (MatchList.Count > 0)
{
bool foundgg = false;
int j = 0;
while (!foundgg && MatchList.Count > j)
{
if (MatchList[j].Groups[1].Value.Substring(MatchList[j].Groups[1].Value.Length - 3, 3) == "jpg")
{
try
{
string guid = Guid.NewGuid().ToString();
webClient.DownloadFile(MatchList[j].Groups[1].Value, @"c:\temp\" + guid + ".jpg");
FileInfo fi = new FileInfo(@"c:\temp\" + guid + ".jpg");
this.image_size = fi.Length;
using (Image img = Image.FromFile(@"c:\temp\" + guid + ".jpg"))
{
int minHeight = this.cov_min_height;
if ((bool)((object[])options)[1])
minHeight = 100;
if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg) && img.HorizontalResolution > 70 && img.Size.Height > minHeight && img.Size.Width > this.cov_min_width && this.image_size < 250000)
{
foundgg = true;
image_name = guid;
image_height = img.Height;
image_width = img.Width;
img.Dispose();
if ((bool)((object[])options)[0])
{
Mediatly.savePoster(this, (bool)((object[])options)[1]);
}
}
else
{
img.Dispose();
File.Delete(@"c:\temp\" + guid.ToString() + ".jpg");
}
}
}
catch (Exception ex)
{
}
}
j++;
}
}
}
webClient.Dispose();
Log.CountImgDec();
}
}
}
public void getPosterAsc(bool save = false, bool banner = false)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(getPoster), new object[2] { save, banner });
}