• 自已写的线程池


    C#有ThreadPool和Task,为什么还要自己写线程池?我以前也没想过自己写线程池,都是用ThreadPool或Task,前段时间写爬虫,我想控制10个线程爬网页、10个线程下载网页上的图片,不然的话因为网页很多,图片相对较少,可能大部分线程都在爬网页,少量线程在下载图片,这样下载图片的速度慢了,所以我想到了自己写线程池MyThreadPool,再配合ThreadPool使用,精确控制爬网页和下载图片的线程数。不过这个线程池写的比较简单,缺点是线程池会瞬间创建最大数量的工作线程。

    线程池类代码:

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace Utils
    {
        /// <summary>
        /// 线程池
        /// </summary>
        public static class MyThreadPool
        {
            /// <summary>
            /// 最大工作线程数
            /// </summary>
            private static int m_WorkerThreads = 5;
            /// <summary>
            /// 线程队列
            /// </summary>
            private static ConcurrentQueue<MyThread> m_ThreadQueue = new ConcurrentQueue<MyThread>();
            /// <summary>
            /// 任务队列
            /// </summary>
            private static ConcurrentQueue<Tuple<Action<object>, object>> m_Action = new ConcurrentQueue<Tuple<Action<object>, object>>();
    
            /// <summary>
            /// 创建并启动线程
            /// </summary>
            /// <param name="action"></param>
            /// <param name="obj"></param>
            public static void Start(Action<object> action, object obj = null)
            {
                m_Action.Enqueue(new Tuple<Action<object>, object>(action, obj));
    
                MyThread thread;
                if (m_ThreadQueue.Count < m_WorkerThreads)
                {
                    thread = new MyThread();
                    m_ThreadQueue.Enqueue(thread);
                    thread.isWorker = true; //设置为工作线程
                    thread.thread = new Thread(new ThreadStart(() =>
                    {
                        Tuple<Action<object>, object> tuple;
                        while (thread.isWorker) //如果是工作线程,则一直循环
                        {
                            if (m_Action.TryDequeue(out tuple)) //如果任务队列中有任务,则取出任务执行
                            {
                                tuple.Item1(tuple.Item2); //执行任务
                            }
                            else
                            {
                                Thread.Sleep(100);
                            }
                            Thread.Sleep(1);
                        }
                    }));
                    thread.thread.IsBackground = true;
                    thread.thread.Start();
                }
            }
    
            /// <summary>
            /// 设置最大工作线程数
            /// </summary>
            /// <param name="workerThreads">最大工作线程数</param>
            public static void SetMaxThreads(int workerThreads)
            {
                m_WorkerThreads = workerThreads;
                MyThread thread = null;
                while (m_ThreadQueue.Count > m_WorkerThreads)
                {
                    m_ThreadQueue.TryDequeue(out thread);
                    thread.isWorker = false;
                    Thread.Sleep(1);
                }
            }
    
            /// <summary>
            /// 获取最大工作线程数
            /// </summary>
            public static int GetMaxThreads()
            {
                return m_WorkerThreads;
            }
    
            /// <summary>
            /// 获取当前工作线程数
            /// </summary>
            public static int GetWorkerThreads()
            {
                return m_ThreadQueue.Count;
            }
        }
    
        /// <summary>
        /// 线程
        /// </summary>
        public class MyThread
        {
            /// <summary>
            /// 线程
            /// </summary>
            public Thread thread { get; set; }
            /// <summary>
            /// 是否工作线程
            /// </summary>
            public bool isWorker { get; set; }
        }
    }
    View Code

    测试代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Common.Utils;
    using System.Collections.Concurrent;
    
    namespace test
    {
        public partial class Form1 : Form
        {
            private static int errorCount = 0;
            private static int errorCount2 = 0;
            private static object _lock = new object();
            private static int dataCount = 30;
            /// <summary>
            /// 任务执行总次数
            /// </summary>
            private static int runCount = 0;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                ThreadPool.SetMaxThreads(20, 20);
                StringBuilder sb = new StringBuilder();
                for (int k = 1; k <= dataCount; k++)
                {
                    sb.AppendFormat("{0},", k.ToString("00"));
                }
                lblMsg2.Text = sb.ToString();
    
                timer1.Tick += new EventHandler((obj, ea) =>
                {
                    int maxThreads = MyThreadPool.GetMaxThreads();
                    int workerThreads = MyThreadPool.GetWorkerThreads();
                    lblMsg.Text = string.Format("{0}/{1}(工作线程数/最大工作线程数)", workerThreads, maxThreads);
                    //ThreadPool.GetMaxThreads(out workerThreads, out maxThreads);
                    //lblMsg.Text = string.Format("{0}/{1}(最大辅助线程数/最大I/O线程数)", workerThreads, maxThreads);
    
                    if (workerThreads > maxThreads)
                    {
                        errorCount++;
                        lblError.Text = "错误(工作线程数超过最大工作线程数)次数:" + errorCount.ToString() + ",错误(线程内代码执行结果错误)次数:" + errorCount2.ToString();
                    }
                    if (lblMsg2.Text != sb.ToString())
                    {
                        errorCount2++;
                        lblError.Text = "错误(工作线程数超过最大工作线程数)次数:" + errorCount.ToString() + ",错误(线程内代码执行结果错误)次数:" + errorCount2.ToString();
                        LogUtil.LogError(lblMsg2.Text);
                    }
                    lblRunCount.Text = "任务执行总次数:" + runCount.ToString();
                });
                timer1.Interval = 100;
                timer1.Start();
                lblError.Text = "暂没有错误";
            }
    
            //开始
            private void button1_Click(object sender, EventArgs e)
            {
                MyThreadPool.SetMaxThreads(20);
                ThreadPool.SetMaxThreads(20, 20);
                button1.Enabled = false;
                Thread thread = new Thread(new ThreadStart(() =>
                {
                    while (true)
                    {
                        List<int> list = new List<int>();
                        for (int i = 1; i <= dataCount; i++)
                        {
                            // ThreadPool.QueueUserWorkItem((obj) =>
                            // Task.Factory.StartNew((obj) =>
                            MyThreadPool.Start((obj) =>
                            {
                                int n = (int)obj;
                                lock (_lock)
                                {
                                    list.Add(n);
                                }
                                if (list.Count == dataCount)
                                {
                                    list.Sort();
                                    StringBuilder sb = new StringBuilder();
                                    for (int k = 0; k < list.Count; k++)
                                    {
                                        sb.AppendFormat("{0},", list[k].ToString("00"));
                                    }
                                    this.Invoke(new MyInvoke(() => { lblMsg2.Text = sb.ToString(); }));
                                    runCount++;
                                }
                            }, i);
                        }
                        Thread.Sleep(1);
                    }
                }));
                thread.IsBackground = true;
                thread.Start();
            }
    
            //设置最大工作线程数
            private void button2_Click(object sender, EventArgs e)
            {
                int d;
                if (int.TryParse(txtMaxThreads.Text, out d))
                {
                    if (d > 0)
                    {
                        MyThreadPool.SetMaxThreads(d);
                        ThreadPool.SetMaxThreads(d, d);
                    }
                    else
                    {
                        txtMaxThreads.Text = "1";
                    }
                }
                else
                {
                    txtMaxThreads.Text = "20";
                }
            }
    
        }
    
        public delegate void MyInvoke();
    }
    View Code

    测试截图:

  • 相关阅读:
    Step download timeout (120 sec)
    Error -27740: WSA_IO_pending
    Message Code 【27796】 Failed to connect to server 'hostname';port_ld': 'reason'.
    Error -27780: Connection reset by peer: socket write error
    LoadRunner性能分析指标解释
    Firefox 在LR录制过程中添加例外的问题解决方法
    -27979 LoadRunner 错误27979 找不到请求表单 Action.c(73): Error -27979: Requested form not found
    MySQL测试环境遇到 mmap(xxx bytes) failed; errno 12解决方法
    基于Apache搭建Nagios图形监控
    自动安装脚本-------------基于LVMP搭建Nagios 监控
  • 原文地址:https://www.cnblogs.com/s0611163/p/6178973.html
Copyright © 2020-2023  润新知