淺談多線程和異步

  最近很忙,因此拿出時間來寫博客也算是忙里偷閑了,繼承前面的一貫風格,繼續淺談胡侃。
  最近在項目中遇到了Socket異步網絡傳輸的問題,所以沉下心來整理下。于是,先問了下度娘,結果找到了園友志良的一篇文章《C#中異步和多線程的區別》(參考文獻1),精讀了一遍,個人覺得理解的很好,自己學習下之余,又動手加工了一下以分享給各位博友,希望各位博友能對異步和多線程有一個清楚的認識。

  C#中異步和多線程的區別是什么呢?異步和多線程兩者都可以達到避免調用線程阻塞的目的,從而提高軟件的可響應性。甚至有些時候我們就認為異步和多線程是等同的概念。但是,異步和多線程還是有一些區別的。而這些區別造成了使用異步和多線程的時機的區別。  

  異步操作的本質

  所有的程序最終都會由計算機硬件來執行,所以為了更好的理解異步操作的本質,我們有必要了解一下它的硬件基礎。 熟悉電腦硬件的朋友肯定對DMA這個詞不陌生,硬盤、光驅的技術規格中都有明確DMA的模式指標,其實網卡、聲卡、顯卡也是有DMA功能的。DMA就是直 接內存訪問的意思,也就是說,擁有DMA功能的硬件在和內存進行數據交換的時候可以不消耗CPU資源。只要CPU在發起數據傳輸時發送一個指令,硬件就開 始自己和內存交換數據,在傳輸完成之后硬件會觸發一個中斷來通知操作完成。這些無須消耗CPU時間的I/O操作正是異步操作的硬件基礎。所以即使在DOS 這樣的單進程(而且無線程概念)系統中也同樣可以發起異步的DMA操作。

  線程的本質

  線程不是一個計算機硬件的功能,而是操作系統提供的一種邏輯功能,線程本質上是進程中一段并發運行的代碼,所以線程需要操作系統投入CPU資源來運行和調度。

  異步操作的優缺點

  因為異步操作無須額外的線程負擔,并且使用回調的方式進行處理,在設計良好的情況下,處理函數可以不必使用共享變量(即使無法完全不用,最起碼可以減少 共享變量的數量),減少了死鎖的可能。當然異步操作也并非完美無暇。編寫異步操作的復雜程度較高,程序主要使用回調方式進行處理,與普通人的思維方式有些出入,而且難以調試。

  多線程的優缺點

  多線程的優點很明顯,線程中的處理程序依然是順序執行,符合普通人的思維習慣,所以編程簡單。但是多線程的缺點也同樣明顯,線程的使用(濫用)會給系統帶來上下文切換的額外負擔。并且線程間的共享變量可能造成死鎖的出現。

  適用范圍

  在了解了線程與異步操作各自的優缺點之后,我們可以來探討一下線程和異步的合理用途。我認為:當需要執行I/O操作時,使用異步操作比使用線程+同步 I/O操作更合適。I/O操作不僅包括了直接的文件、網絡的讀寫,還包括數據庫操作、Web Service、HttpRequest以及.net Remoting等跨進程的調用。

  而線程的適用范圍則是那種需要長時間CPU運算的場合,例如耗時較長的圖形處理和算法執行。但是往往由于使用線程編程的簡單和符合習慣,所以很多朋友往往會使用線程來執行耗時較長的I/O操作。這樣在只有少數幾個并發操作的時候還無傷大雅,如果需要處理大量的并發操作時就不合適了。

  異步的一個示例

  大家可能都知道,使用delegate可以“自動”使一個方法可以進行異步的調用。從直覺上來說,我覺得是由編譯器或者CLR使用了另外的線程來執行目標方法。到底是不是這樣呢?

using System;
using System.Threading;
namespace 異步
{delegate void AsyncFoo(int i);class Program{/// ﹤summary﹥   /// 輸出當前線程的信息   /// ﹤/summary﹥      /// ﹤param name="name"﹥方法名稱﹤/param﹥    static void PrintCurrThreadInfo(string name){Console.WriteLine("Thread Id of " + name + " is: " + Thread.CurrentThread.ManagedThreadId + ", current thread is "+ (Thread.CurrentThread.IsThreadPoolThread ? "" : "not ") + "thread pool thread.");}/// ﹤summary﹥   /// 測試方法,Sleep一定時間   /// ﹤/summary﹥   /// ﹤param name="i"﹥Sleep的時間﹤/param﹥   static void Foo(int i){PrintCurrThreadInfo("Foo()");Thread.Sleep(i);}/// ﹤summary﹥   /// 投遞一個異步調用   /// ﹤/summary﹥   static void PostAsync(){AsyncFoo caller = new AsyncFoo(Foo);caller.BeginInvoke(1000, new AsyncCallback(FooCallBack), caller);}static void Main(string[] args){PrintCurrThreadInfo("Main()");for (int i = 0; i < 5; i++){PostAsync();}Console.ReadLine();}static void FooCallBack(IAsyncResult ar){PrintCurrThreadInfo("FooCallBack()");AsyncFoo caller = (AsyncFoo)ar.AsyncState;caller.EndInvoke(ar);}}
}

程序的輸出如下:

看樣子答案是肯定的。

這個示例程序很好,基本上可以說是一個異步的使用規范模板了吧,個中含義不多說了。

參考文獻:

C#中異步和多線程的區別

C#網絡Socket編程(基本概念和操作) - Part.1,2,,3,4,5

題外話:
  經過將近3周(16天)的艱苦奮戰,今天上午,終于把公司現有的一個項目升級成為異步,醫院現場測試通過!其中涉及兩塊,一塊是客戶端的門診醫生站程序,另一塊是服務器端!而后者的升級,對DebugLZQ現在所在的創業型公司來講,也許提升的競爭力不是一點兩點,因為不同的系統可以共用這個服務器!
  DebugLZQ也再一次真切的體會到了,實驗室的產品走上商用,要經過的一些列的種種麻煩----網絡傳輸速度、(大)數據并發、用戶體驗、數據庫系統的可靠性、程序的穩定性(異常恢復)、軟件系統安全性,甚至有時需要考慮到一些軟硬件環境的問題。陪著“老板”一路走過來,著實不易!個中滋味,只有DebugLZQ知道。

  可能很快DebugLZQ就要離開現在的這個公司,因為馬上要畢業了,還是希望師弟師妹們能把技術傳承下去,也希望“老板”的公司茁壯成長,做強做大!

  

轉載于:https://www.cnblogs.com/DebugLZQ/archive/2012/09/05/2670986.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379349.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379349.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379349.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

查看Sql Server的log文件大小

SELECT DB_NAME(database_id) AS DatabaseName,Name AS Logical_Name,Physical_Name, (size*8)/1024 SizeMBFROM sys.master_filesWHERE DB_NAME(database_id) AdventureWorksGO 轉載于:https://www.cnblogs.com/top5/archive/2010/03/02/1676776.html

python調用帶參函數_Python | 帶有示例的函數調用類型

python調用帶參函數There are following types of function calls in python: python中有以下類型的函數調用&#xff1a; Call by value 按價值致電 Call by reference 通過參考電話 1)按價值致電 (1) Call by value ) When, we call a function with the values i.e. pass …

ffmpeg 命令添加文字水印

使用ffplay 預覽一下效果&#xff1a; ffplay -i cctvhttp.flv -vf “drawtextfontsize100:fontfileArial.ttf:tex t‘hello world’:x20:y20:fontcolorblue:alpha0.5” -x 640 -y 480 使用ffmpeg保存為文件 &#xff1a; ffmpeg -i cctvhttp.flv -vf “drawtextfontsize10…

jquery彈出層

這是一個彈出層的插件&#xff0c;有時候做東西的&#xff0c;經常會用到了&#xff0c;所以在次發一下&#xff0c;和大家分享一下&#xff01; [task]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/x…

MUL與IMUL區別(微機原理與接口技術 第2版)課后習題3.14、P123

MUL與IMUL的詳細區別 乘數位數隱含的被乘數乘積的存放位置舉例8位ALAX中MUL BL16位AXDX與AX中&#xff08;DX存放高16位、AX存放低16位&#xff09;MUL BX 課本P97例題 一&#xff09;、將以下指令中的立即數看作是無符號數實現相乘: MOV AL,0B4H ;ALB4H180 解釋以下&…

SDL_main導致main找不到入口

SDL main的錯誤 引用SDL.h就會報這個錯誤 因為SDL 將main 宏定義為 SDL_main,所以會找不到main入口 可以使用#undef main取消這個宏定義

Java MathContext類| hashCode()方法與示例

MathContext類的hashCode()方法 (MathContext Class hashCode() method) hashCode() method is available in java.math package. hashCode()方法在java.math包中可用。 hashCode() method is used to get the hash code value of this MathContext. hashCode()方法用于獲取此M…

實驗8 SQL Server 的存儲過程

實驗8 SQL Server 的存儲過程一、實驗目的 1.掌握使用T-SQL編程的方法 2.掌握使用T-SQL語句創建一個存儲過程并驗證 3.掌握創建和執行帶參數的存儲過程 4.熟練使用系統存儲過程、系統函數 二、實驗要求 1.創建一個不帶參數的存儲過程。 2.創建一個帶參數的存儲過程p_count。 三…

Oracle ——如何確定性能差的 SQL

http://www.toadworld.com/KNOWLEDGE/KnowledgeXpertforOracle/tabid/648/TopicID/TSQ7/Default.aspx 本文主要說明在應用程序內書寫和調優 SQL 語句。假設&#xff0c;你已經知道你應用程序中的哪些 SQL 語句需要注意。事實上&#xff0c;這不太容易。那么&#xff0c;我們如何…

C#中的委托和事件(續)

http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html 歡迎瀏覽本文的后續文章&#xff1a; C#中的委托和事件(續)PDF 瀏覽&#xff1a;http://www.tracefact.net/Document/Delegates-and-Events-in-CSharp.pdf文中代碼在VS2005下通過&#xff0c;由于VS2003(.Ne…

Java LocalDate類| minusYears()方法與示例

LocalDate類minusYears()方法 (LocalDate Class minusYears() method) minusYears() method is available in java.time package. minusYears()方法在java.time包中可用。 minusYears() method is used to subtract the given years from this LocalDate and return the LocalD…

ffmpeg 命令添加圖片水印

使用ffplay預覽一下&#xff1a; ffplay -i cctvhttp.flv -vf “moviewatermark.png[watermark];[in][watermark]overlay x10:y10[out]” -x 640 -y 480 參數&#xff1a; 有兩個過濾器movie\overlay movie&#xff1a;讀取watermark.png輸出 [watermark]可以理解自定義的的變…

實驗9 SQL Server 的觸發器

實驗9 SQL Server 的觸發器一、實驗目的 1.了解觸發器的觸發過程和類型 2.通過執行SQL腳本&#xff0c;掌握創建觸發器并測試觸發器 3.掌握通過使用觸發器維護數據完整性的方法。 二、實驗要求 1.按指定要求創建觸發器。 三、實驗步驟 1.創建一個名為tr_age的觸發器&#xff0…

struts2學習筆記二--準備struts2的學習和開發環境

準備struts2的學習和開發環境1 導包2 參照開發包自帶的例子在web.xml文件中配置3 參照開發包自帶的例子編寫Action類和配置struts.xml文件<struts><package name"demo" namespace"/hello/word"><action name"test" class"cn…

C#實現動態桌面背景圖片切換

問題描述&#xff1a;凝視桌面背景&#xff0c;突感如果桌面背景是變化的像win7一樣&#xff0c;該多有意思啊。鬧鐘瞬間產生一個念頭&#xff0c;用C#寫一個動態切換桌面背景的圖片。如何實現這個想法了&#xff0c;我思考了一會兒&#xff0c;想到了如下的一些需要解決的問題…

duration java_Java Duration類| withSeconds()方法與示例

duration java持續時間類withSeconds()方法 (Duration Class withSeconds() method) withSeconds() method is available in java.time package. withSeconds()方法在java.time包中可用。 withSeconds() method is used to represent this Duration with the given seconds. wi…

ffmpeg 命令畫中畫效果

畫中畫效果也是和圖片水印一樣使用movie配合overlay實現 使用ffplay預覽一下&#xff1a; ffplay -i cctvhttp.flv -vf “moviecctvhttp.flv[subm];[in][subm]overlayx20:y30[o ut]” -x 640 -y 480 &#xff08;可以看到是有兩層視頻的&#xff09; 用個不同的視頻再測試&…

實驗10 SQL Server 數據備份/恢復

實驗10 SQL Server 數據備份/恢復一、實驗目的 1.了解數據庫備份的過程和屬性設置&#xff1b; 2.掌握應用企業管理器備份和恢復數據庫&#xff1b; 3.掌握應用T-SQL備份和恢復數據庫&#xff1b; 4.掌握數據導入/導出的方法。 二、實驗要求 1.創建指定數據庫的備份. 2.恢復數…

指針和數組

數組的概念與指針的概念聯系非常解密。其實數組的標識相當于它的第一個元素的地址&#xff0c;就像一個指針相當于它所指向的第一個元素的地址&#xff0c;因此其實它們是同一個東西 int numbers [20];int * p;下面的賦值為合法的&#xff1a; p numbers; 這里指針p 和numbers…

程序集(初嘗,也是為插件程序準備)

拓展名是EXE或者DLL的.net可執行程序稱為程序集。 .net程序集與一般的EXE&#xff0c;DLL的區別在于&#xff0c;它包含有metadata。 私有程序集 位于應用程序的目錄下。共享程序集 必須有一個特殊的版本號&#xff0c;唯一的名稱&#xff0c;通常安裝在全局程序集緩存&#xf…