gpt4 book ai didi

c# - 这些 1k 线程来自哪里

转载 作者:行者123 更新时间:2023-11-30 12:25:58 24 4
gpt4 key购买 nike

我正在尝试创建一个多线程从网站下载图像的应用程序,作为对线程的介绍。 (之前从未正确使用线程)

但目前它似乎创建了 1000 多个线程,我不确定它们来自哪里。

我首先将一个线程排入线程池,对于初学者来说,我在作业数组中只有 1 个作业

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 张图像。

最佳答案

首先,您是如何测量线程数的?为什么您认为您的应用程序中有数千个?您正在使用 ThreadPool,因此您不会自己创建它们,ThreadPool 也不会根据需要创建如此大量的它们。

其次,您在代码中混合了同步和异步操作。由于您不能使用 TPLasync/await,让我们检查您的代码并计算您正在创建的 unit-of-works,所以你可以最小化它们。执行此操作后,ThreadPool 中排队的项目数将减少,您的应用程序将获得所需的性能。

  1. 您没有设置 SetMaxThreads应用程序中的方法,因此,according the MSDN :

    Maximum Number of Thread Pool Threads
    The number of operations that can be queued to the thread pool is limited only by available memory; however, the thread pool limits the number of threads that can be active in the process simultaneously. By default, the limit is 25 worker threads per CPU and 1,000 I/O completion threads.

    因此您必须将最大值设置为 5

  2. 我在您的代码中找不到检查每个作业的 42 图像的位置,您只是在 ProcessPage 方法中增加值。

  3. 检查 ManagedThreadId 以获取 WebClient.DownloadStringCompleted 的句柄 - 它是否在不同的线程中执行。
  4. 你在ThreadPool 队列中添加新项目,为什么要使用异步操作进行下载?使用synchronious overload ,像这样:

    ProcessPage(wc.DownloadString(downloadLink), false, j);

    这不会在 ThreadPool 队列中创建另一个项目,并且您不会在此处进行同步上下文切换。

  5. ProcessPage 中,您的 wc 变量没有被垃圾回收,因此您没有在这里释放所有资源。在此处添加 using 语句:

    void ProcessPage(string response, bool secondPass, Job j)
    {
    using (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);
    }
    }
    }
    }
    }
  6. DownloadImage 方法中,您还使用了异步加载。这也会在 ThreadPoll 队列中添加项目,我认为您可以避免这种情况,并使用 synchronious overload也是:

    wc.DownloadFile(url, id + ext);
    return true;

因此,一般来说,避免上下文切换操作并妥善处理您的资源。

关于c# - 这些 1k 线程来自哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30176171/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com