大話非同步與並行(二)

来源: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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...