Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这些1k线程来自哪里_C#_Multithreading_Unity3d_.net 3.5_.net 2.0 - Fatal编程技术网

C# 这些1k线程来自哪里

C# 这些1k线程来自哪里,c#,multithreading,unity3d,.net-3.5,.net-2.0,C#,Multithreading,Unity3d,.net 3.5,.net 2.0,我试图创建一个多线程的应用程序,从一个网站下载图像,作为对线程的介绍。(以前从未正确使用过螺纹) 但目前它似乎创建了1000多个线程,我不确定它们来自哪里 我首先将一个线程排队到线程池中,首先,我在作业数组中只有一个作业 foreach (Job j in Jobs) { ThreadPool.QueueUserWorkItem(Download, j); } 它在一个新线程上启动void下载(objectobj),在该线程中循环一定数量的页面(需要图像/42个图像/页面) 最后传递到

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

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

我首先将一个线程排队到线程池中,首先,我在作业数组中只有一个作业

foreach (Job j in Jobs)
{
    ThreadPool.QueueUserWorkItem(Download, j);
}
它在一个新线程上启动void
下载(objectobj)
,在该线程中循环一定数量的页面(需要图像/42个图像/页面)

最后传递到最后一个函数并下载实际图像

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

您的wc WebLinet将超出范围,并在异步回调之前被随机垃圾收集。此外,在所有异步调用上,您必须允许立即返回和实际的委托函数返回。因此processPage必须位于两个位置。此外,原始循环中的j可能超出范围,具体取决于原始循环中的下载位置

首先,你是如何测量线程数的?为什么你认为你的申请中有上千个呢?您使用的是
ThreadPool
,因此您不能自己创建它们,
ThreadPool
也不会根据需要创建这么多

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

  • 您没有在应用程序中设置方法,因此:

    线程池线程的最大数量
    可排队到线程池的操作数仅受可用内存的限制; 但是,线程池限制了可以访问的线程数 同时活跃在这个过程中默认情况下,限制为25 每个CPU的工作线程和1000个I/O完成线程。

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

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

  • 检查
    ManagedThreadId
    以获取
    WebClient.DownloadStringCompleted
    的句柄-它是否在不同的线程中执行
  • 您正在
    ThreadPool
    队列中添加新项目,为什么要使用异步操作进行下载?使用一个类似这样的工具:

    ProcessPage(wc.DownloadString(downloadLink), false, j);
    
    这将不会在
    ThreadPool
    队列中创建另一个项目,并且这里不会有Sinchronization上下文开关

  • ProcessPage
    中,您的
    wc
    变量没有被垃圾收集,因此您没有在此处释放所有资源。在此处使用
  • 语句添加

    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);
                    }
                }
            }
        }
    }
    
  • DownloadImage
    方法中,还可以使用异步加载。这也会在
    ThreadPoll
    队列中添加项,我认为您可以避免这种情况,也可以使用:


  • 因此,一般来说,避免上下文切换操作,并正确地配置资源。

    在另一个线程中运行异步操作。为什么不直接使用异步呢?在这种情况下,线程为您提供了什么好处?@Tigran可能没有,只是尝试了解线程的诀窍,在线程情况下使用阻塞调用而不是异步调用是否更有意义?如果您使用异步,请不要使用线程。如果要控制并发工作负载,请使用线程,以便根据需要跨多个线程,而不是更多。VS:Debug->Windows->threads。它应该解释为什么你有这么多线程。(也不知道你为什么贴上unity3d标签——也许有什么特别之处)。@AlexeiLevenkov在unity引擎(游戏引擎)中制作,它的功能比普通的.net有限。
    ProcessPage(wc.DownloadString(downloadLink), false, j);
    
    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);
                    }
                }
            }
        }
    }
    
    wc.DownloadFile(url, id + ext);
    return true;