【发布时间】:2015-07-22 11:01:20
【问题描述】:
我正在尝试创建一个多线程从网站下载图像的应用程序,作为线程的介绍。 (以前从未正确使用过线程)
但目前它似乎创建了 1000 多个线程,我不确定它们来自哪里。
我首先将一个线程排队到线程池中,对于初学者来说,作业数组中只有一个作业
foreach (Job j in Jobs)
{
ThreadPool.QueueUserWorkItem(Download, j);
}
它在一个新线程上启动 void Download(object obj),它循环一定数量的页面(需要的图像/每页 42 个图像)
for (var i = 0; i < pages; i++)
{
var downloadLink = new System.Uri("http://www." + j.Provider.ToString() + "/index.php?page=post&s=list&tags=" + j.Tags + "&pid=" + i * 42);
using (var wc = new WebClient())
{
try
{
wc.DownloadStringAsync(downloadLink);
wc.DownloadStringCompleted += (sender, e) =>
{
response = e.Result;
ProcessPage(response, false, j);
};
}
catch (System.Exception e)
{
// Unity editor equivalent of console.writeline
Debug.Log(e);
}
}
}
如果我错了,请纠正我,下一个 void 会在同一个线程上调用
void ProcessPage(string response, bool secondPass, Job j)
{
var wc = new WebClient();
LinkItem[] linkResponse = LinkFinder.Find(response).ToArray();
foreach (LinkItem i in linkResponse)
{
if (secondPass)
{
if (string.IsNullOrEmpty(i.Href))
continue;
else if (i.Href.Contains("http://loreipsum."))
{
if (DownloadImage(i.Href, ID(i.Href)))
j.Downloaded++;
}
}
else
{
if (i.Href.Contains(";id="))
{
var alterResponse = wc.DownloadString("http://www." + j.Provider.ToString() + "/index.php?page=post&s=view&id=" + ID(i.Href));
ProcessPage(alterResponse, true, j);
}
}
}
}
最后传递到最后一个函数,下载实际图片
bool DownloadImage(string target, int id)
{
var url = new System.Uri(target);
var fi = new System.IO.FileInfo(url.AbsolutePath);
var ext = fi.Extension;
if (!string.IsNullOrEmpty(ext))
{
using (var wc = new WebClient())
{
try
{
wc.DownloadFileAsync(url, id + ext);
return true;
}
catch(System.Exception e)
{
if (DEBUG) Debug.Log(e);
}
}
}
else
{
Debug.Log("Returned Without a extension: " + url + " || " + fi.FullName);
return false;
}
return true;
}
我不确定我是如何开始这么多线程的,但我很想知道。
编辑
此程序的目标是同时下载不同作业中的作业(最多 5 个),每个作业一次最多下载 42 张图像。
所以在任何时候都可以/应该最多下载 210 张图片。
【问题讨论】:
-
你在另一个线程中运行异步操作。为什么不只使用异步,就是这样。 ?在这种情况下,线程为您提供了哪些好处?
-
@Tigran 可能没有,只是想掌握线程的窍门,然后在线程情况下使用阻塞调用而不是异步调用更有意义吗?
-
如果你使用异步,不要使用线程。如果您要控制并发工作负载,请使用线程,因此根据需要跨越尽可能多的线程,而不是更多。
-
VS:调试->Windows->线程。它应该解释为什么你有这么多线程。 (也不知道你为什么用 unity3d 标记帖子 - 也许它有什么特别之处)。
-
@AlexeiLevenkov 在统一引擎(游戏引擎)中制作它,与通常的 .net 相比,它的功能有限。
标签: c# multithreading unity3d .net-3.5 .net-2.0