如何寫個死循環,既不獨占線程,又不阻塞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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM