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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

大话异步与并行(一)

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

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

本博文寫的主旨是用最白話的語(yǔ)言來(lái)說明問題,不想照搬概念。

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

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

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

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

下面來(lái)說說異步自然缺少不了多線程這個(gè)重頭戲。

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

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;}} }

一直都在想一個(gè)問題,為什么這種方式名字叫投票!百度 google都沒有結(jié)果,最后想著想著也就想清楚了,所謂投票,就是對(duì)結(jié)果的一種猜測(cè),“是否結(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);}} }

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

如果說到這里,那么,我想微軟也太失敗了,因?yàn)檫@樣玩異步太操心,那么多的代碼。

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

好吧,我們對(duì)上面的代碼是時(shí)候要簡(jiǎn)化的必要了。

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();}} }

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

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

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

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

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

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

看下面代碼

?

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

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

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

?

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

?

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

總結(jié)

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

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