日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

大话异步与并行(一)

發(fā)布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 大话异步与并行(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

很久沒安下心來寫博客了,幾年的開發(fā)過程中,對于異步與并行的了解也隨著清淅起來。首先很多人問我,異步與并行的區(qū)別,那么我們來了解下概念。

本博文寫的主旨是用最白話的語言來說明問題,不想照搬概念。

在古老的單核計算機(jī)中,一般是單核的,并行也只是在進(jìn)程中交替的執(zhí)行,表現(xiàn)出來的像并行執(zhí)行一樣,只是時間比較短,在多核處理器的計算機(jī)中,進(jìn)程不僅可以交替執(zhí)行,而且可以重疊執(zhí)行,所以說,并行,只有在多核處理器中才有真正意義。很多人可能會突然不理解,并行與并發(fā),是什么區(qū)別,并行,就像兩種時刻相同的進(jìn)程同一時刻運(yùn)行,而并發(fā)不一定同一時刻運(yùn)行,這就微妙的區(qū)別。

就拿訂單來說吧,在下單超大的情況下,A用戶下了一個訂單,還沒有來及結(jié)束,B用戶又下了一個訂單。那么,這時最有可能發(fā)行的情況就是并發(fā)事件。

那么我們今天重點說說異步,異步,是相對于同步來說的,我們知道,應(yīng)用程序都是由一個主線程來運(yùn)行的,這個主線程,是按照順序來處理我們寫的邏緝代碼的,這就是同步,引用異步的好處是,在不打撓主線程的前提下,繼續(xù)開放一個線程來指行其它的事情,就相當(dāng)于,把部分工作交接給別人,當(dāng)別人做好了后,然后,對我說,你交待的任務(wù)我已做好了。別人做好的工作交待給我的過程,相當(dāng)于結(jié)果的返回中斷。

異步最終的目的就是給我們帶來更高效的時間效應(yīng),它是一種結(jié)果,而實現(xiàn)這個異步的可能是異步委托,線程池,線程等等,只不過是一種方法或途徑罷了,這就是線程與異步的最好詮釋。

下面來說說異步自然缺少不了多線程這個重頭戲。

實現(xiàn)多線程方式很多,下面一個一個的講起。

1.投票

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ConsoleApplication1 {class Program{public delegate decimal TakeDelegate(decimal data, int ms); static void Main(string[] args) {DateTime now = DateTime.Now;TakeDelegate dl = SaveBankAccount;IAsyncResult ar= dl.BeginInvoke(1, 200, null, null);while(!ar.IsCompleted){Console.WriteLine("main thread wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Thread.Sleep(50);}decimal result = dl.EndInvoke(ar);Console.WriteLine("CurrentMoney:{0}", result);Console.WriteLine("runtime:{0}", (DateTime.Now-now).TotalSeconds);Console.WriteLine("main thread IsBackground " + Thread.CurrentThread.IsBackground);Console.ReadKey();}static decimal SaveBankAccount(decimal money,int ms){Console.WriteLine("SaveBankAccount thread started! current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Console.WriteLine("SaveBankAccount thread IsBackground " + Thread.CurrentThread.IsBackground);Thread.Sleep(ms);Console.WriteLine("SaveBankAccount thread completed!");return ++money;}} }

一直都在想一個問題,為什么這種方式名字叫投票!百度 google都沒有結(jié)果,最后想著想著也就想清楚了,所謂投票,就是對結(jié)果的一種猜測,“是否結(jié)束投票”


2.異步回調(diào)

?

?

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ConsoleApplication1 {class Program{public delegate decimal TakeDelegate(decimal money,int ms);static DateTime now = DateTime.Now;static void Main(string[] args) {TakeDelegate dl = SaveBankAccount;var ar = dl.BeginInvoke(1, 200, AsyncCallBack,dl);while(!ar.IsCompleted){Console.WriteLine("main thread wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Thread.Sleep(50);}Console.ReadKey();}static decimal SaveBankAccount(decimal money,int ms){Console.WriteLine("SaveBankAccount thread started! current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Console.WriteLine("SaveBankAccount thread IsBackground " + Thread.CurrentThread.IsBackground);Thread.Sleep(ms);Console.WriteLine("SaveBankAccount thread completed!");return ++money;}static void AsyncCallBack(IAsyncResult ar){if (ar == null){throw new ArgumentNullException("ar");}TakeDelegate dl = ar.AsyncState as TakeDelegate;decimal result = dl.EndInvoke(ar);Console.WriteLine("CurrentMoney:{0}", result);Console.WriteLine("runtime:{0}", (DateTime.Now - now).TotalSeconds);Console.WriteLine("main thread IsBackground " + Thread.CurrentThread.IsBackground);}} }

這個方法是在投票的基礎(chǔ),加入了回調(diào)函數(shù)而已。還有一種方法于投票差不多,就是等待句柄(AsyncWaitHandle),這個方法與投票沒有太大的差異。沒事的同學(xué)可以百度一下,這里就不多說了。

如果說到這里,那么,我想微軟也太失敗了,因為這樣玩異步太操心,那么多的代碼。

隨著時間的推移,微軟在.net3.0 C# 3.0的大包裹越來越健全 拉姆達(dá)(lambda)表達(dá)式與匿名方法?孕育而生。

好吧,我們對上面的代碼是時候要簡化的必要了。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ConsoleApplication1 {class Program{static void Main(string[] args){DateTime now = DateTime.Now;Func<decimal, int, decimal> f = SaveBankAccount;var ar = f.BeginInvoke(1, 200, (r) =>{if (r == null){throw new ArgumentNullException("r");}Console.WriteLine("CurrentMoney:{0}", f.EndInvoke(r));Console.WriteLine("runtime:{0}", (DateTime.Now - now).TotalSeconds);Console.WriteLine("main thread IsBackground " + Thread.CurrentThread.IsBackground);}, null);while (!ar.IsCompleted){Console.WriteLine("main thread wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Thread.Sleep(50);}Console.ReadKey();}static decimal SaveBankAccount(decimal money, int ms){Console.WriteLine("SaveBankAccount thread started! current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Console.WriteLine("SaveBankAccount thread IsBackground " + Thread.CurrentThread.IsBackground);Thread.Sleep(ms);Console.WriteLine("SaveBankAccount thread completed!");return ++money;}} }

?

再次狠狠的優(yōu)化

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ConsoleApplication1 {class Program{static void Main(string[] args){DateTime now = DateTime.Now;Func<decimal, int, decimal> f = (money, ms) =>{Console.WriteLine("SaveBankAccount thread started! current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Console.WriteLine("SaveBankAccount thread IsBackground " + Thread.CurrentThread.IsBackground);Thread.Sleep(ms);Console.WriteLine("SaveBankAccount thread completed!");return ++money;};var ar = f.BeginInvoke(1, 200, (r) =>{if (r == null){throw new ArgumentNullException("r");}Console.WriteLine("CurrentMoney:{0}", f.EndInvoke(r));Console.WriteLine("runtime:{0}", (DateTime.Now - now).TotalSeconds);Console.WriteLine("main thread IsBackground " + Thread.CurrentThread.IsBackground);}, null);while (!ar.IsCompleted){Console.WriteLine("main thread wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);Thread.Sleep(50);}Console.ReadKey();}} }

著重看下兩個劃框的部分,lambda表達(dá)式采用匿名方法成功的簡化了傳統(tǒng)的方式,里面的參數(shù)獲取,將來的更為便捷,所以四個參數(shù)后,用了null。

public delegate TResult Func<in T, out TResult>(T arg)?委托 是微軟在.net 3.5 再次對delegate的封裝,第一個參數(shù)是輸入?yún)?shù),第二個是返回參數(shù),此時,我們不用太辛苦的到處聲明委托,這點微軟也給我們省了,不得不說,代碼的優(yōu)美不是java能比的。

細(xì)心的朋友可能看到上面一段代碼 IsBackground 這個時候,表示線程是前臺線程還是后臺線程。

前臺線程與后臺線程的區(qū)別:

就像word文檔一樣,打開word 即開啟了word主線程即前臺線程,諸如 語法檢查屬于后臺線程,仔細(xì)想想,這樣設(shè)計,還是有道理的,當(dāng)關(guān)閉了word前臺主線程,后臺線程語法檢查也沒有必要了。

一個進(jìn)程里必須有一個前臺線程,不一定有后臺線程。當(dāng)前臺線程已結(jié)束的時候,后臺線程也將結(jié)束。

看下面代碼

?

通常,應(yīng)該將被動偵聽活動的線程設(shè)置為后臺線程,而將負(fù)責(zé)發(fā)送數(shù)據(jù)的線程設(shè)置為前臺線程,這樣,在所有的數(shù)據(jù)發(fā)送完畢之前該線程不會被終止。只有在確認(rèn)線程被系統(tǒng)隨意終止沒有不利影響時,才應(yīng)該使用后臺線程。如果線程正在執(zhí)行必須完成的敏感操作或事務(wù)操作,或者需要控制關(guān)閉線程的方式以便釋放重要資源,則使用前臺線程。

例如 《C#高級編程》中有個例子--如果關(guān)閉Word程序,拼寫檢查器還在運(yùn)行其進(jìn)程就沒有意義了。在關(guān)閉應(yīng)用程序時拼寫檢查器線程就可以關(guān)閉。

?小結(jié):本節(jié)只是對于基礎(chǔ)知識線程與異步委托作了個簡單的復(fù)習(xí),讓我聯(lián)想到,主線程也好,新開的線程也好,無非都是線程的部分,線程更多的是一種方法,而異步是一個需要線程支撐的結(jié)果,所以可以在任何線程上開啟異步的操作,因為主線程都可以開啟異步嘛。

?

?未完待續(xù)...

?

轉(zhuǎn)載于:https://www.cnblogs.com/laogu2/p/5885880.html

總結(jié)

以上是生活随笔為你收集整理的大话异步与并行(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。