如何寫個死迴圈,既不獨占線程,又不阻塞UI線程?

来源:https://www.cnblogs.com/s0611163/archive/2020/06/17/13154263.html
-Advertisement-
Play Games

如果死迴圈獨占線程,500個死迴圈要占用500個線程,如果死迴圈不獨占線程,500個死迴圈,用200個線程也行,用20個線程也行,無非是執行的慢點 這樣可以把同步操作改寫為非同步,並且節省線程占用 問個問題:寫個Socket服務端,接收數據不准用BeginReceive和ReceiveAsync,只能 ...


如果死迴圈獨占線程,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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 遞歸,是一個非常重要的概念,也是面試中非常喜歡考的。因為它不但能考察一個程式員的演算法功底,還能很好的考察對時間空間複雜度的理解和分析。 本文只講一題,也是幾乎所有演算法書講遞歸的第一題,但力爭講出花來,在這裡分享四點不一樣的角度,讓你有不同的收穫。 時空複雜度的詳細分析 識別並簡化遞歸過程中的重 ...
  • ...
  • Python學習之路——pycharm的第一個項目 簡介: 上文中已經介紹如何安裝Pycharm已經環境變數的配置。現在軟體已經安裝成功,現在就開始動手做第一個Python項目。第一個“Hello World”項目。 第一步:打開Pycharm軟體 1.雙擊,桌面圖標,運行軟體,進入軟體後,點擊“C ...
  • 響應式編程 命令式編程(Imperative Programing),是一種描述電腦所需做出的行為的編程範式。詳細的命令機器怎麼(How)去處理以達到想要的結果(What)。 聲明式編程(Declarative Programing),是一種編程範式,與命令式編程相對立。它描述目標的性質,讓電腦 ...
  • 作者:邊鵬_尛爺鑫 https://segmentfault.com/a/1190000010844969 大家心裡仔細想想,當你們聽到高併發網站時,心裡對這個網站是個什麼概念? 首先想到的是淘寶嗎?帶著問題,我們一起思考技術~ 寫這個話題是因為我對搜索引擎給我的答案很不滿意,然後決定把思考的一些東 ...
  • 1.封裝的作用 程式設計要追求”高內聚,低耦合“ 高內聚:類的內部數據操作細節自己完成,不允許外部干涉。 低耦合:僅暴露少量的方法給外部使用,儘量方便外部調用。 類似設計電視,冰箱也是,外部看起來很簡單,就幾個開關,方便使用。內部很複雜,不對外展示。 封裝的概念就產生於此,把對象的屬性和操作結合為一 ...
  • 進去黑客世界,跟著我學習-python-02-while迴圈.py ...
  • 0.前言 在上一篇中,我們提到瞭如何創建一個UnitOfWork並通過ActionFilter設置啟用。這一篇我們將簡單介紹一下ActionFilter以及如何利用ActionFilter,順便補齊一下上一篇的工具類。 1. ActionFilter 介紹 ActionFilter全稱是Action ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...