苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 13333|回复: 8

[其他] 请教一下线程池的问题!

[复制链接]
发表于 2021-2-20 16:49:34 | 显示全部楼层 |阅读模式
我写一个程序,可能最大的时候需要同时开启100个线程。

我采用了线程池去处理这个事情。

然后恶心的事情来了。   我按照规章制度。

首先:   Threadpool.SetMinThreads(1,1),然后Threadpool.SetMaxThreads(100,100);

处理好基本设置后,我每一次的投递任务( ThreadPool.QueueUserWorkItem() )  之前,我都调用ThreadPool.GetAvailableThreads来获取空闲线程数有多少。

有多少我循环投递多少。可是,实际结果是  每一次都能获取到还有很多空闲线程。我已经投递了几百上千个任务出去了,按照道理来说,早已经塞满线程池了。可是为什么还是检索到这么多空闲线程。

而且根据处理进度来看。好像不管我开多少线程。每一次最多只能帮我处理20多个任务。

我的任务函数是一个    http的get访问网页的代码而已,然后判断了一下字符串。就这样。

麻烦各位大佬解惑啊,好多天了,完全无头绪,百度的资料千篇一律。




1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2021-2-21 10:23:07 | 显示全部楼层
1. 可能是执行快,执行完了
2. 可能是投递失败,具体的你可以贴全一点的代码看看
发表于 2021-2-21 16:37:47 | 显示全部楼层
处理好基本设置后,我每一次的投递任务( ThreadPool.QueueUserWorkItem() )  之前,我都调用ThreadPool.GetAvailableThreads来获取空闲线程数有多少。

这个步骤你可以去掉试试,上面设置过Max可以不用判断,未测试仅理论
 楼主| 发表于 2021-2-22 11:09:05 | 显示全部楼层
C:\Users\Administrator\Desktop\1.1.png
 楼主| 发表于 2021-2-22 14:35:35 | 显示全部楼层
[C#] 纯文本查看 复制代码
/// <summary>
        /// 工作主线程
        /// </summary>
        /// <param name="obj"></param>

        private void ThreadWork()
        {
            int WorkerThreadsMax = 0, WorkerThreadsAv = 0;

            //用户设置大于1000个线程是没有意义的。线程池最多支持1000个线程同时工作。
            formsPram.WorkThreadNumber = formsPram.WorkThreadNumber > 1000 ? 1000 : formsPram.WorkThreadNumber;

            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(formsPram.WorkThreadNumber, formsPram.WorkThreadNumber);

            //初始化扫描数据
            InitiaData();

            long speed = formsPram.NumberStart;

            //解除http访问高并发限制,如果不设置该值.只能同时并发2 - 10个数据
            ServicePointManager.DefaultConnectionLimit = 512;
            while (!Stopeed)
            {
                ThreadPool.GetMaxThreads(out WorkerThreadsMax, out int CompletionPrortThreadsMax);
                ThreadPool.GetAvailableThreads(out WorkerThreadsAv, out int CompletionPrortThreadsAv);

                //设置显示空闲线程数
                SetFreeThreadNumber(WorkerThreadsAv);
                //显示正在工作的线程数
                SetWorkerThreadNumber(WorkerThreadsMax - WorkerThreadsAv);
                //设置显示一下找到的个数。
                SetSuccessNum();
                //设置已经扫描的个数
                SetHandleNum();

                if (WorkerThreadsAv > 0 && formsPram.NumberStart < formsPram.NumberEnd)
                {
                    for (int i = 0; i < WorkerThreadsAv; i++)
                    {
                        if (TaskIndex >= weblist.Count)
                        {
                            break;
                        }
                        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolTask), weblist[TaskIndex++]);
                    }
                    Debug.WriteLine($"投递了{WorkerThreadsAv}个任务出去");
                }
                //检查一下是否已经抓取完毕了
                if (TaskIndex >= weblist.Count)
                {
                    AddLog("任务投递完成,等待子线程执行完毕后程序自动停止。");
                    break;
                }
                Thread.Sleep(1000);
            }

            while (true)
            {
                ThreadPool.GetMaxThreads(out WorkerThreadsMax, out int CompletionPrortThreadsMax);
                ThreadPool.GetAvailableThreads(out WorkerThreadsAv, out int CompletionPrortThreadsAv);
                if (WorkerThreadsMax != WorkerThreadsAv)
                {
                    AddLog($"正在等待子线程结束,还剩余{WorkerThreadsMax - WorkerThreadsAv} 个任务正在执行");
                }
                else
                {
                    break;
                }
                Thread.Sleep(1000);
            }
            BtnStart.Invoke(new Action(() =>
            {
                BtnStart.Enabled = true;

            }));
            AddLog("主线程停止了工作!");
        }

  /// <summary>
        /// 任务线程池
        /// </summary>
        private void ThreadPoolTask(object obj)
        {

            DateTime dateTime = DateTime.Now;



            var str = Work.HttpRequest(formsPram.WaitingTime, obj.ToString());

            DateTime dateTime2 = DateTime.Now;

            TimeSpan timeSpan = dateTime2 - dateTime;

            if (timeSpan.TotalMilliseconds >= 4000)
            {
                AddLog($"线程超过4000毫秒才执行完成,总计耗时{timeSpan.TotalMilliseconds}毫秒");
            }

            // Debug.WriteLine($"耗时 {timeSpan.TotalMilliseconds} 毫秒 " + obj.ToString());
            lock (objLock)
            {
                HandleNum++;
            }
            if (str.Contains(formsPram.Features1) && str.Contains(formsPram.Features2))
            {
                AddLog($"找到 {formsPram.InterfaseClass} ,域名是{obj}");
                lock (objLock)
                {
                    SuccessNum++;
                }
                CreateFiles($"类型:{formsPram.InterfaseClass} ---- 域名: {obj}");
                return;
            }

        }

/// <summary>
        /// GET方式 访问网页
        /// </summary>
        /// <param name="Timeout">访问超时限定</param>
        /// <param name="Address">要访问的网址</param>
        /// <returns></returns>
        public static string HttpRequest(int Timeout, string Address)
        {
            if (string.IsNullOrEmpty(Address))
            {
                return "";
            }
            try
            {
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(Address);
                webRequest.Method = "GET";
                webRequest.Timeout = Timeout;
                webRequest.ReadWriteTimeout = Timeout;
                webRequest.KeepAlive = false;
                HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
                StreamReader sr = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8);
                var str = sr.ReadToEnd();
                webRequest.Abort();
                webResponse.Close();
                sr.Close();
                return str;
            }
            catch (Exception)
            {
                return "";
            }
           
        }
 楼主| 发表于 2021-2-23 20:48:37 | 显示全部楼层
站长苏飞 发表于 2021-2-21 10:23
1. 可能是执行快,执行完了
2. 可能是投递失败,具体的你可以贴全一点的代码看看

大佬 帮忙看看吧。代码我贴上来了
发表于 2021-9-11 16:46:53 | 显示全部楼层
啥也看不懂呢
发表于 2021-10-1 02:53:50 | 显示全部楼层
线程池推荐用SmartThreadPool,比原生的好很多,有n种对线程的管理方式
发表于 2021-10-5 21:24:54 | 显示全部楼层
等待大佬出现 ..........路过
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-12-25 16:08

© 2014-2021

快速回复 返回顶部 返回列表