C# 多线程 自定义线程池

 

关于限制,HttpWebRequest最大连接数限制

.Net中并发连接限制数量默认是2,意思就是说,哪怕你开100条线程同时进行请求,有效的连接数仍是2条,解决办法就是在App.config中修改配置.

C# 关于HttpWebRequest最大连接数限制,多线程中速度提升解决方案_PLA12147111的博客-CSDN博客_httpwebrequest 最大连接数.Net中并发连接限制数量默认是2,意思就是说,哪怕你开100条线程同时进行请求,有效的连接数仍是2条,解决办法就是在App.config中修改配置.↓↓↓↓↓↓↓↓↓↓↓↓↓↓解决方案↓↓↓↓↓↓↓↓↓↓↓↓↓↓1.打开App.config2.原来的3.添加并发连接限制设置代码:<?xml version="1.0" encoding="utf-8...https://blog.csdn.net/PLA12147111/article/details/105496791?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167645444216800186594251%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167645444216800186594251&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-105496791-null-null.article_score_rank_blog&utm_term=C%23%20%E5%85%B3%E4%BA%8EHttpWebRequest&spm=1018.2226.3001.4450

    /// <summary>
    /// 测试代码
    /// </summary>
    public static void Test()
    {
        TaskPool_new _taskPool = new TaskPool_new();

        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        for (var i = 0; i < 20; i++)
        {
            _taskPool.AddTaskItem(() => Console.WriteLine("我是通过Lambda表达式创建的委托"));
        }
    }

    public static void Test2()
    {
//创建50个线程,同时执行
        var taskPoo = new TaskPool_new(50);
        Console.WriteLine("date ======== " + DateTime.Now.ToString("mm:ss:fff"));
       // TaskPool_new _taskPool = new TaskPool_new(100);
        for (var i = 0; i < 10; i++)
        {
            int t = i;
            taskPoo.AddTaskItem(() => 
            {
                var delay = RandomEx.Random(50, 7900);
                Thread.Sleep(delay);
                Console.WriteLine("date = " + DateTime.Now.ToString("mm:ss:fff")  + " ,delay =" + delay + " ,ThreadId= " + Thread.CurrentThread.ManagedThreadId + " ,i= " + t);

            });
        }
        Console.WriteLine("date ========= " + DateTime.Now.ToString("mm:ss:fff"));
    }

TaskPool_new.cs 

/*
1.程序一启动就通过for循环来创建,一定数目的线程(这个数目是可以配置的)

2.至少要有三个容器来存储线程,分别是工作线程队列和空闲线程队列以及等待队列

3.使用线程中的AutoResetEvent类,初始每一个线程都是unsignaled状态,线程一启动就一直在循环调用WaitOne()方法,那么每次外部调用的时候,都调用一次这个类实例对象的set,线程然后就可以继续做下面的工作了。

4.至少两个方法:

第一个开放给外部,让外部的方法能够被传入执行,然后这个方法能够判断空闲队列,等待队列,以及工作队列的状态,如果传入的时候发现,空闲队列有空闲的线程就直接,将任务委托给空闲队列的一个线程执行,否则把它放到等待队列。

第二个方法,需要能够将工作完成的线程从工作队列移动到空闲队列,然后判断一下等待队列是不是有任务,有的话就交给空闲队列里面的线程来执行。

体思路如上,可以试试先写一下。

1.因为每个线程都有一个AutoResetEvent的实例,所以最好把Thread进行封装,变成我们自己的Thread。

*/
using System;
using System.Collections.Generic;
using System.Threading;


/// <summary>
/// 自定义线程池
/// </summary>
public class TaskPool_new
{
    #region Variable
    /// <summary>
    /// 创建的线程数
    /// </summary>
    private int _threadCount;
    /// <summary>
    /// 空闲线程队列
    /// </summary>
    private Queue<Task_new> _freeQueue;
    /// <summary>
    /// 工作线程字典
    /// </summary>
    private Dictionary<string, Task_new> _workingDictionary;
    /// <summary>
    /// 空闲队列,存放需要被执行的外部函数
    /// </summary>
    private Queue<Action> _waitQueue;
    #endregion

    #region Event


    /// <summary>
    /// 自定义线程池的构造函数
    /// </summary>
    /// <param name="threadCount">创建的线程数</param>
    public TaskPool_new(int threadCount = 10)
    {
        _workingDictionary = new Dictionary<string, Task_new>();
        _freeQueue = new Queue<Task_new>();
        _waitQueue = new Queue<Action>();
        _threadCount = threadCount;

        Task_new task = null;
        //产生固定数目的线程
        for (int i = 0; i < _threadCount; i++)
        {
            task = new Task_new();
            //给每一个任务绑定事件
            task.WorkComplete += new Action<Task_new>(WorkComplete);
            //将每一个新创建的线程放入空闲队列中
            _freeQueue.Enqueue(task);
        }
    }

    /// <summary>
    /// 线程任务完成之后的工作
    /// </summary>
    /// <param name="obj"></param>
    void WorkComplete(Task_new obj)
    {
        lock (this)
        {
            //将线程从字典中排除
            _workingDictionary.Remove(obj.Key);
            //将该线程放入空闲队列
            _freeQueue.Enqueue(obj);

            //判断是否等待队列中有任务未完成
            if (_waitQueue.Count > 0)
            {
                //取出一个任务
                Action item = _waitQueue.Dequeue();
                Task_new newTask = null;
                //空闲队列中取出一个线程
                newTask = _freeQueue.Dequeue();
                // 线程执行任务
                newTask._taskAction = item;
                //把线程放入到工作队列当中
                _workingDictionary.Add(newTask.Key, newTask);
                //设置信号量
                newTask.Active();
                return;
            }
            else
            {
                return;
            }
        }
    }

    /// <summary>
    /// 添加任务到线程池
    /// </summary>
    /// <param name="taskItem"></param>
    public void AddTaskItem(Action taskItem)
    {
        lock (this)
        {
            Task_new task = null;
            //判断空闲队列是否存在线程
            if (_freeQueue.Count > 0)
            {
                //存在线程,取出一个线程
                task = _freeQueue.Dequeue();
                //将该线程放入工作队列
                _workingDictionary.Add(task.Key, task);
                //执行传入的任务
                task._taskAction = taskItem;
                //设置信号量
                task.Active();
                return;
            }
            else
            {
                //空闲队列中没有空闲线程,就把任务放到等待队列中
                _waitQueue.Enqueue(taskItem);
                return;
            }
        }
    }
    #endregion

    /// <summary>
    /// 测试代码
    /// </summary>
    public static void Test()
    {
        TaskPool_new _taskPool = new TaskPool_new();

        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        for (var i = 0; i < 20; i++)
        {
            _taskPool.AddTaskItem(() => Console.WriteLine("我是通过Lambda表达式创建的委托"));
        }
    }

    public static void Test2()
    {
        var taskPoo = new TaskPool_new(50);
        Console.WriteLine("date ======== " + DateTime.Now.ToString("mm:ss:fff"));
       // TaskPool_new _taskPool = new TaskPool_new(100);
        for (var i = 0; i < 10; i++)
        {
            int t = i;
            taskPoo.AddTaskItem(() => 
            {
                var delay = RandomEx.Random(50, 7900);
                Thread.Sleep(delay);
                Console.WriteLine("date = " + DateTime.Now.ToString("mm:ss:fff")  + " ,delay =" + delay + " ,ThreadId= " + Thread.CurrentThread.ManagedThreadId + " ,i= " + t);

            });
        }
        Console.WriteLine("date ========= " + DateTime.Now.ToString("mm:ss:fff"));
    }
}


public class Task_new
{
    #region Variable
    //一个AutoResetEvent实例
    private AutoResetEvent _locks = new AutoResetEvent(false);
    //一个Thread实例
    private Thread _thread;
    // 绑定回调方法,就是外部实际执行的任务
    public Action _taskAction;

    //定义一个事件用来绑定工作完成后的操作,工作队列向空闲队列移动
    public event Action<Task_new> WorkComplete;

    /// <summary>
    ///设置线程拥有的Key
    /// </summary>
    public string Key { get; set; }

    #endregion

    /// <summary>
    /// 线程需要做的工作
    /// </summary>
    private void Work()
    {
        while (true)
        {
            //判断信号状态,如果有set那么 _locks.WaitOne()后的程序就继续执行
            _locks.WaitOne();
            _taskAction();
            //执行事件
            WorkComplete(this);
        }
    }

    #region event
    //构造函数
    public Task_new()
    {
        _thread = new Thread(Work);
        _thread.IsBackground = true;
        Key = Guid.NewGuid().ToString();
        //线程开始执行
        _thread.Start();
    }

    //Set开起信号
    public void Active()
    {
        _locks.Set();
    }

    #endregion
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值