zoukankan      html  css  js  c++  java
  • 如何写个死循环,既不独占线程,又不阻塞UI线程?

    如果死循环独占线程,500个死循环要占用500个线程,如果死循环不独占线程,500个死循环,用200个线程也行,用20个线程也行,无非是执行的慢点

    这样可以把同步操作改写为异步,并且节省线程占用

    问个问题:写个Socket服务端,接收数据不准用BeginReceive和ReceiveAsync,只能用Receive,Socket客户端10000个,线程池最大不准超过1000,如何实现?

    网上是用Select模型,要维护一个Socket对象列表,如果用下面的代码,可以不用维护Socket对象列表,直接有多少Socket对象,就写多少while(true)

    代码:

    using System;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Utils;
    
    /**
     * 如何写个死循环,既不独占线程,又不阻塞UI线程
    */
    
    namespace test
    {
        public partial class Form1 : Form
        {
            private int _n = 0;
            private bool _run1 = false;
            private bool _run2 = false;
            private TaskSchedulerEx _task1 = new TaskSchedulerEx(2, 2); //只给2个线程
    
            public Form1()
            {
                InitializeComponent();
                ThreadPool.SetMaxThreads(12, 12); //最多给12个线程
                ThreadPool.SetMinThreads(10, 10);
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
            }
    
            /// <summary>
            /// 测试1
            /// 现象:会输出i=5,也会输出i=15,button3有事件响应,因为20个死循环,2个线程也能处理,只不过处理速度慢,加大线程池容量可加快处理速度
            /// </summary>
            private void button1_Click(object sender, EventArgs e)
            {
                _n = 0;
                button1.Enabled = false;
                button2.Enabled = true;
                _run1 = true;
                _run2 = false;
                textBox1.Text = string.Empty;
                for (int i = 1; i <= 20; i++) //启动20个死循环
                {
                    _task1.Run(async (obj) => //用_task1(只给2个线程)启动20个死循环
                    {
                        dynamic var = (dynamic)obj;
    
                        while (_run1) //此while不会独占线程
                        {
                            Task t = Task.Factory.StartNew(() =>
                            {
                                Thread.Sleep(100);
                                Interlocked.Increment(ref _n);
    
                                if (var.i == 5 || var.i == 15)
                                {
                                    int a1; int a2; int m1; int m2;
                                    ThreadPool.GetMaxThreads(out m1, out a1);
                                    ThreadPool.GetAvailableThreads(out m2, out a2);
                                    Log("当前使用辅助线程数:" + (m1 - m2) + ",当前使用异步线程数:" + (a1 - a2) + ",i=" + var.i + ",n=" + _n);
                                }
                            });
                            await t;
                        }
                    }, new { i = i });
                }
            }
    
            /// <summary>
            /// 测试2 
            /// 现象:只输出i=5,不输出i=15,button3不能响应事件,因为有20个死循环,12个线程不够用,但因为12个线程比较多,所以处理速度较快
            /// </summary>
            private void button2_Click(object sender, EventArgs e)
            {
                _n = 0;
                button1.Enabled = true;
                button2.Enabled = false;
                _run1 = false;
                _run2 = true;
                textBox1.Text = string.Empty;
                for (int i = 1; i <= 20; i++) //启动20个死循环
                {
                    Task.Factory.StartNew((obj) => //用Task(最多12个线程)启动20个死循环
                    {
                        dynamic var = (dynamic)obj;
    
                        while (_run2) //此while会独占一个线程
                        {
                            Thread.Sleep(100);
                            Interlocked.Increment(ref _n);
    
                            if (var.i == 5 || var.i == 15)
                            {
                                int a1; int a2; int m1; int m2;
                                ThreadPool.GetMaxThreads(out m1, out a1);
                                ThreadPool.GetAvailableThreads(out m2, out a2);
                                Log("当前使用辅助线程数:" + (m1 - m2) + ",当前使用异步线程数:" + (a1 - a2) + ",i=" + var.i + ",n=" + _n);
                            }
                        }
                    }, new { i = i });
                }
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                Task.Factory.StartNew(() =>
                {
                    Log("button3_Click 有响应"); //测试button3是否能响应事件
                });
            }
        }
    }
    View Code
  • 相关阅读:
    Git 总结
    .net报错大全
    对于堆和栈的理解
    html 局部打印
    c#面试问题总结
    算法题总结
    h5-plus.webview
    堆和栈,引用类型,值类型,指令,指针
    .NET framework具体解释
    前端之间的url 传值
  • 原文地址:https://www.cnblogs.com/s0611163/p/13154263.html
Copyright © 2011-2022 走看看