大話非同步與並行(二)

来源:http://www.cnblogs.com/laogu2/archive/2016/09/19/5887116.html
-Advertisement-
Play Games

接著上期的文章繼續說非同步與並行 並行來自於線程的方法實現,非同步不一定。這句話,暈倒一大片程式員。 首先,多線程式是實現非同步一種方法,兩者的共同目的:使主線程保持對用戶操作的實時響應,如點擊、拖拽、輸入字元等。使主程式看起來實時都保持著等待用戶響應的狀態,而後臺卻有若幹件事情在自己乾。按消耗資源所在地 ...


接著上期的文章繼續說非同步與並行

並行來自於線程的方法實現,非同步不一定。這句話,暈倒一大片程式員。

首先,多線程式是實現非同步一種方法,兩者的共同目的:使主線程保持對用戶操作的實時響應,如點擊、拖拽、輸入字元等。使主程式看起來實時都保持著等待用戶響應的狀態,而後臺卻有若幹件事情在自己乾。按消耗資源所在地可分為兩類:硬體非同步類和CPU非同步類。

硬體非同步的特點:將需要在後臺執行的操作甩給底層硬體去執行,不占用線程和CPU資源。所以說,並不是所有的非同步都占有線程的。

硬體非同步類大概有以下這幾類。

應用程式範圍

支持包含非同步方法的 API

Web 訪問

HttpClient ,SyndicationClient

處理文件

StorageFileStreamWriterStreamReaderXmlReader

使用圖像處理

MediaCaptureBitmapEncoderBitmapDecoder

WCF 編程

同步和非同步操作

與套接字處理

Socket

 

CPU常用的非同步方式、方法

1、獨立的線程—ThreadStart

     一般情況下,要為不會阻止其他線程的相對較短的任務處理多個線程並且不需要對這些任務執行任何特定調度時,使用 ThreadPool 類是一種最簡單的方式。 但是,有多個理由創建您自己的線程:

  • 如果您需要使一個任務具有特定的優先順序。

  • 如果您具有可能會長時間運行(並因此阻止其他任務)的任務。

  • 如果您需要將線程放置到單線程單元中(所有 ThreadPool 線程均處於多線程單元中)。

  • 如果您需要與該線程關聯的穩定標識。 例如,您應使用一個專用線程來中止該線程,將其掛起或按名稱發現它。

  • 如果您需要運行與用戶界面交互的後臺線程,.NET Framework 2.0 版提供了 BackgroundWorker 組件,該組件可以使用事件與用戶界麵線程的跨線程封送進行通信。

2、ThreadPool—ThreadPool.QueueUserWorkItem(M())

3、任務,Task系列--普通任務、關聯的任務(Task<T>.ContinueWith(…))、父子任務、任務工廠(TaskTactory<TResult>)

4、Parallel靜態類--- System.Threading.Tasks.Parallel.For(…) System.Threading.Tasks.Parallel.ForEach(…) Parallel.Invoke(() => Sort());

5、PLINQ

6、定時器  

到此只是簡單的基礎知識闡述。如果不太清楚,下麵的陸續的文章將會一一講起。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Thread類(線程類)

除了使用委托創建線程之外,還可以使用thread 類創建線程

        static void Main(string[] args)
        {
            Thread t = new Thread(ThreadMain);
            t.Start();
            Console.WriteLine("This ia a mian thread.");
        }

        static void ThreadMain()
        {
            Console.WriteLine("Running in a thread.");
        }

簡化以上代碼 

 static void Main(string[] args)
        {
            new Thread(() =>
            Console.WriteLine("Running in a thread.")

        ).Start();
          
            Console.WriteLine("This ia a mian thread.");
        }

再次見證  拉姆達(lambda)表達式與匿名方法 的威力。

在上面簡單的Thread類就創建並開始了一個線程。Thread類預設的是 IsBackground =false,也就是說它是前臺線程。

說到前臺線程與後臺線程,上一文章提到,當前臺進程停止的時候,後臺進程也將停止,當時是放在mian主線程測試的,必須關閉或結束主線程,看的不是太清楚

現在有了Thread類,下麵的例子將會開啟不依懶主線程的測試。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime now = DateTime.Now;

            Thread t1 = new Thread(() =>
            {
                Console.WriteLine("Running in a thread t1.");
                Func<decimal, int, decimal> f = (money, ms) =>
                {
                    Console.WriteLine("SaveBankAccountPersonA thread started! current run at threadID:" + Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine("SaveBankAccountPersonA thread IsBackground " + Thread.CurrentThread.IsBackground);
                    Thread.Sleep(ms);
                    Console.WriteLine("SaveBankAccountPersonA thread completed!");
                    return ++money;
                };

                var ar = f.BeginInvoke(1, 200, (r) =>
                {
                    if (r == null)
                    {
                        throw new ArgumentNullException("r");
                    }

                    Thread.Sleep(1000);

                    Console.WriteLine("AsycyCallBackCurrentMoneyPersonA:{0}", f.EndInvoke(r));
                    Console.WriteLine("AsycyCallBackRunTimePersonA:{0}", (DateTime.Now - now).TotalSeconds);
                    Console.WriteLine("AsycyCallBackSaveBankAccountPersonA thread IsBackground " + Thread.CurrentThread.IsBackground);

                }, null);

                while (!ar.IsCompleted)
                {
                    Console.WriteLine("threadT1 wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(50);
                }
            });

            Thread t2 = new Thread(() =>
            {

                Console.WriteLine("Running in a thread t2.");
                Func<decimal, int, decimal> f = (money, ms) =>
                {
                    Console.WriteLine("SaveBankAccountPersonB thread started! current run at threadID:" + Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine("SaveBankAccountPersonB thread IsBackground " + Thread.CurrentThread.IsBackground);
                    Thread.Sleep(ms);
                    Console.WriteLine("SaveBankAccountPersonB thread completed!");
                    return ++money;
                };

                var ar = f.BeginInvoke(1, 200, (r) =>
                {
                    if (r == null)
                    {
                        throw new ArgumentNullException("r");
                    }
                    Console.WriteLine("AsycyCallBackCurrentMoneyPersonB:{0}", f.EndInvoke(r));
                    Console.WriteLine("AsycyCallBackRunTimePersonB:{0}", (DateTime.Now - now).TotalSeconds);
                    Console.WriteLine("AsycyCallBackSaveBankAccountPersonB thread IsBackground " + Thread.CurrentThread.IsBackground);

                }, null);

                while (!ar.IsCompleted)
                {
                    Console.WriteLine("threadT2 wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(50);
                }
            });

            t1.Start();
            t2.Start();
            t1.Abort();

            Console.WriteLine("This ia a mian thread.");
            Console.ReadKey();
        }
    }
}

上面的代碼很多,對上一文章的進行擴展。分別啟用兩個線程t1和t2 ,併在每個線程裡加入非同步委托A和B,從而開始新的後臺線程(非同步委托預設是後臺線程)

上面這張圖,t1還沒有來及運行,就已停止,下麵這張圖,t1運行起來了

但是A還是沒有運行起來,充分說明A一併被t1停止

 

後臺線程A和B 同時擁有兩個回調函數 ,在A回調函數里 加入了Sleep(1000) 延遲1秒,緊接著外面t1.Abort();結束前臺線程t1。從而達到,外面的t1前臺線程結束時後臺線程A還沒有來及結束(實際上已強制性並隨t1前臺線程結束了!)

這樣就驗證了,前臺線程結束所依懶的後臺線程所並隨結束的事實!代碼就是最好的說明

 

小結:本節在文章一節中著重闡述的前臺線程與後臺線程作了在Thread類基礎上做了實例論證,從而證明,後臺線程的生命周期由依懶的前臺線程結束而結束。

同時也將非同步與多線程進一步舉例說明,線程只是非同步的一種實現方法!

 

 未完待續...

 


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

-Advertisement-
Play Games
更多相關文章
  • 1.資料庫名為Demo,數據結構如圖 2.後臺代碼如下 ...
  • 1. 類和結構能夠實現介面 2. 介面聲明包含如下四種類型:屬性、方法、事件和索引;這些函數聲明不能包含任何實現代碼,而在每一個成員的主體後必須使用分號 3. 繼承介面的類或結構必須實現介面中的所有成員 4. 顯示介面的實現註意下麵的代碼 ...
  • 走進非同步編程的世界 - 在 WinForm 中執行非同步操作 序 這是繼《開始接觸 async/await 非同步編程》、《走進非同步編程的世界 - 剖析非同步方法》後的第三篇。主要介紹在 WinForm 中如何執行非同步操作。 目錄 在 WinForm 程式中執行非同步操作 在 WinForm 中使用非同步 L ...
  • 背水一戰 Windows 10 之 控制項(進度類): RangeBase, Slider, ProgressBar, ProgressRing ...
  • 配置針對應用程式的運行狀況監視的一個服務 配置節內容比以往的較為複雜,如下 實際上這是運行狀況監視是一個事件定義與處理的模型,簡單來看整個運行狀況監視基本點有以下三個 1.在eventMappings定義事件 2.在providers定義事件的處理 3.通過rules綁定事件給某個處理程式去處理。 ...
  • Awesome系列的.Net資源整理。awesome-dotnet是由quozd發起和維護。內容包括:編譯器、壓縮、應用框架、應用模板、加密、資料庫、反編譯、IDE、日誌、風格指南等。 API 框架 NancyFx:輕量、用於構建 HTTP 基礎服務的非正式(low-ceremony)框架,基於.N ...
  • 代碼: 方法一:窗體的代碼-->可以直接通過預設的Click事件來實現控制進度條。 方法二:通過調用其他類里的方法來實現對進度條的控制。 註意一:需要using System.Windows.Forms; 註意二:進度條ToolStripProgressBar的許可權需要改成Public 效果圖:(左 ...
  • 前言 我們知道,在 MVC 應用程式中,有一部分約定的內容。其中關於 Controller 的約定是這樣的。 每個 Controller 類的名字以 Controller 結尾,並且放置在 Controllers 目錄中。 Controller 使用的視圖是在 Views 主目錄的一個子目錄中,這個 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...