C#線程學習筆記三:線程池中的I/O線程

来源:https://www.cnblogs.com/atomy/archive/2019/12/05/11984179.html
-Advertisement-
Play Games

本筆記摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/20/MultiThreads.html,記錄一下學習過程以備後續查用。 一、I/O線程實現對文件的非同步 1.1 I/O線程介紹: 對於線程所執行的任務來說,可以把線程分為兩種類型:工作者線程和 ...


    本筆記摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/20/MultiThreads.html,記錄一下學習過程以備後續查用。

    一、I/O線程實現對文件的非同步

    1.1 I/O線程介紹:

    對於線程所執行的任務來說,可以把線程分為兩種類型:工作者線程和I/O線程。

    工作者線程用來完成一些計算的任務,在任務執行的過程中,需要CPU不間斷地處理,所以,在工作者線程的執行過程中,CPU和線程的資源是充分利用的。

    I/O線程主要用來完成輸入和輸出的工作,在這種情況下, 電腦需要I/O設備完成輸入和輸出的任務。在處理過程中,CPU是不需要參與處理過程的,此時正在運行的線程

將處於等待狀態,只有等任務完成後才會有事可做, 這樣就造成線程資源浪費的問題。為瞭解決這樣的問題,可以通過線程池來解決這樣的問題,讓線程池來管理線程。

    對於I/O線程,我們可以將輸入輸出操作分成三個步驟:啟動、實際輸入輸出、處理結果。用於實際輸入輸出可由硬體完成,並不需要CPU的參與,而啟動和處理結果也可以

不在同一個線程上,這樣就可以充分利用線程資源。在.Net中通過以Begin開頭的方法來完成啟動,以End開頭的方法來處理結果,這兩個方法可以運行在不同的線程,這樣我們

就實現了非同步編程了。

    1.2 .Net中如何使用非同步

    註意:

    其實當我們調用Begin開頭的方法,就是將一個I/O線程排入到線程池中(由.Net機制幫我們實現)。

    註:工作者線程由線程池管理,直接調用ThreadPool.QueueUserWorkItem方法來將工作者線程排入到線程池中。

    在.NET Framework中的FCL中有許多類型能夠對非同步操作提供支持,其中在FileStream類中就提供了對文件的非同步操作的方法。

    FileStream類要調用I/O線程要實現非同步操作,首先要建立一個FileStream對象,然後通過下麵的構造函數來初始化FileStream對象實現非同步操作(非同步讀取和非同步寫入):

    public FileStream (string path, FileMode mode, FileAccess access, FileShare share,int bufferSize,bool useAsync)

    其中path代表文件的相對路徑或絕對路徑,mode代表如何打開或創建文件,access代表訪問文件的方式,share代表文件如何由進程共用,buffersize代表緩衝區的大小,

useAsync代表使用非同步I/O還是同步I/O,設置為true時,表示使用非同步I/O。

    下麵代碼演示非同步寫入文件:

    class Program
    {
        static void Main(string[] args)
        {
            #region I/O線程:非同步寫入文件
            const int maxSize = 100000;
            ThreadPool.SetMaxThreads(1000, 1000);
            PrintMessage("Main thread start.");

            //初始化FileStream對象
            FileStream fileStream = new FileStream("Test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 100, true);

            //列印文件流打開的方式
            Console.WriteLine("Filestream is {0}opened with asynchronously.", fileStream.IsAsync ? "" : "not ");

            byte[] writeBytes = new byte[maxSize];
            string writeMessage = "An operation use asynchronous method to write message......";
            writeBytes = Encoding.Unicode.GetBytes(writeMessage);
            Console.WriteLine("Message sizes is:{0} bytes.\n", writeBytes.Length);
            //調用非同步寫入方法將信息寫入到文件中
            fileStream.BeginWrite(writeBytes, 0, writeBytes.Length, new AsyncCallback(EndWriteCallback), fileStream);
            fileStream.Flush();
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 列印線程池信息
        /// </summary>
        /// <param name="data"></param>
        private static void PrintMessage(string data)
        {
            //獲得線程池中可用的工作者線程數量及I/O線程數量
            ThreadPool.GetAvailableThreads(out int workThreadNumber, out int ioThreadNumber);

            Console.WriteLine("{0}\n CurrentThreadId is:{1}\n CurrentThread is background:{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is:{4}\n",
                data,
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.IsBackground.ToString(),
                workThreadNumber.ToString(),
                ioThreadNumber.ToString());
        }

        /// <summary>
        /// 當數據寫入文件完成後調用此方法來結束非同步寫操作
        /// </summary>
        /// <param name="asyncResult"></param>
        private static void EndWriteCallback(IAsyncResult asyncResult)
        {
            Thread.Sleep(500);
            PrintMessage("Asynchronous method start.");

            FileStream filestream = asyncResult.AsyncState as FileStream;

            //結束非同步寫入數據
            filestream.EndWrite(asyncResult);
            filestream.Close();
        }
    }

    運行結果如下:

    從運行結果可以看出,此時是調用線程池中的I/O線程去執行回調函數的,同時在項目的bin\Debug文件目錄下生成了一個Test.txt文件。

    下麵代碼演示非同步讀取文件:

    class Program
    {
        //非同步讀取文件
        const int maxSize = 1024;
        private static readonly byte[] readBytes = new byte[maxSize];

        static void Main(string[] args)
        {
            #region I/O線程:非同步讀取文件
            ThreadPool.SetMaxThreads(1000, 1000);
            PrintMessage("Main thread start.");

            // 初始化FileStream對象
            FileStream fileStream = new FileStream("Test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 100, false);

            // 非同步讀取文件內容
            fileStream.BeginRead(readBytes, 0, readBytes.Length, new AsyncCallback(EndReadCallback), fileStream);
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 列印線程池信息
        /// </summary>
        /// <param name="data"></param>
        private static void PrintMessage(string data)
        {
            //獲得線程池中可用的工作者線程數量及I/O線程數量
            ThreadPool.GetAvailableThreads(out int workThreadNumber, out int ioThreadNumber);

            Console.WriteLine("{0}\n CurrentThreadId is:{1}\n CurrentThread is background:{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is:{4}\n",
                data,
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.IsBackground.ToString(),
                workThreadNumber.ToString(),
                ioThreadNumber.ToString());
        }

        /// <summary>
        /// 當數據讀取文件完成後調用此方法來結束非同步寫操作
        /// </summary>
        /// <param name="asyncResult"></param>
        private static void EndReadCallback(IAsyncResult asyncResult)
        {
            Thread.Sleep(1000);
            PrintMessage("Asynchronous method start.");

            // 把AsyncResult.AsyncState轉換為State對象
            FileStream readStream = (FileStream)asyncResult.AsyncState;
            int readLength = readStream.EndRead(asyncResult);
            if (readLength <= 0)
            {
                Console.WriteLine("Read error.");
                return;
            }

            string readMessage = Encoding.Unicode.GetString(readBytes, 0, readLength);
            Console.WriteLine("Read message is :" + readMessage);
            readStream.Close();
        }
    }

    運行結果如下:

    二、I/O線程實現對請求的非同步

    我們同樣可以利用I/O線程來模擬瀏覽器對伺服器請求的非同步操作,在.NET類庫中的WebRequest類提供了非同步請求的支持。

    下麵代碼演示非同步請求:

    class Program
    {
        static void Main(string[] args)
        {
            #region I/O線程:非同步請求
            ThreadPool.SetMaxThreads(1000, 1000);
            PrintMessage("Main thread start.");

            // 發出一個非同步Web請求
            WebRequest webrequest = WebRequest.Create("https://www.cnblogs.com/");
            webrequest.BeginGetResponse(ProcessWebResponse, webrequest);

            Console.Read();
            #endregion
        }

        /// <summary>
        /// 列印線程池信息
        /// </summary>
        /// <param name="data"></param>
        private static void PrintMessage(string data)
        {
            //獲得線程池中可用的工作者線程數量及I/O線程數量
            ThreadPool.GetAvailableThreads(out int workThreadNumber, out int ioThreadNumber);

            Console.WriteLine("{0}\n CurrentThreadId is:{1}\n CurrentThread is background:{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is:{4}\n",
                data,
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.IsBackground.ToString(),
                workThreadNumber.ToString(),
                ioThreadNumber.ToString());
        }

        /// <summary>
        /// Web請求回調函數
        /// </summary>
        /// <param name="result"></param>
        private static void ProcessWebResponse(IAsyncResult result)
        {
            Thread.Sleep(500);
            PrintMessage("Asynchronous method start.");

            WebRequest webRequest = (WebRequest)result.AsyncState;
            using (WebResponse wr = webRequest.EndGetResponse(result))
            {
                Console.WriteLine("Content length is : " + wr.ContentLength);
            }
        }
    }

    運行結果如下:


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

-Advertisement-
Play Games
更多相關文章
  • 添加源 sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 安裝Nginx sudo yum install -y nginx 直到出現 Co ...
  • 摘要:HALCON數據類型:Iconic Variables(圖形變數)、Control Variables(控制變數)。在C#中,圖形變數用HObject聲明,控制變數用HTuple聲明。(halcon數據類型被封裝成類)。 一,HALCON中變數導成C#變數 1,圖形變數 圖像變數 HObjec ...
  • 由於之前在網上查閱一些資料發現總是不能編譯通過,不能正常使用,現把能正常使用的代碼貼出: /// <summary> /// Excel導入幫助類 /// </summary> public class ImportExcelUtil<T> where T : new() { //合法文件擴展名 p ...
  • [toc] C (讀作 “See Sharp”)是一種簡單易用的新式編程語言,不僅面向對象,還類型安全。 C 源於 C 語言系列,可用 C 構建在多種操作系統(平臺)上運行的軟體組件和應用程式。 因為本系列文章會廣泛地使用 C 代碼示例,所以我們先來看看 C 程式的樣子,還有它的不同部分代表什麼意思 ...
  • 因為之前沒有接觸NPOI過這個插件,所以幾乎都是自己一邊百度摸索一邊學習。 這個插件對於Excel的數據導入和導出,可以說是很方便了, 但是對於導出word文檔,可以說是很少的,百度了很多....也不停止地去試代碼,於是整理出自己的一些看法,方便記錄代碼。 話不多說,上代碼... 用這個插件你需要準 ...
  • AMP(加速的移動頁面)是Google的開發人員軟體包,它允許開發負載更快的輕量級系統。AMP是由HTML,JavaScript和CSS組成的框架,它們是為用戶提供Web內容優先格式的標準。 Aspose.Email for .NET是一套全面的電子郵件處理API,可用於構建跨平臺應用程式。近期的更 ...
  • 1、先創建 .net core Web 應用程式,選擇API 2、安裝 Nuget 包:Nlog.Web.AspNetCore install-package Nlog install-package Nlog.Web.AspNetCore 或者打開Nuget管理界面搜索Nlog.Web.AspNe ...
  • 什麼是過濾器? 過濾器的類型與作用 定義過濾器 授權過濾器 動作過濾器 結果過濾器 異常處理過濾器 過濾器的使用方法 總結 什麼是過濾器? 通過上一篇關於Controller控制器的文章我們知道,MVC中的每一個請求,都會分配給相應的控制器(Controller)和對應的行為方法(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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...