非同步多執行緒 1 利用委託Action Func

2022-06-27 15:30:13 字數 4427 閱讀 5166

基礎概念

程序:程式執行時,佔據的計算資源的合集,稱為程序,如qq、word都是乙個程序。

程序之間不會互相干擾。

執行緒:依託於程序,乙個程序可以有多個執行緒,它是程式執行的最小單位,響應操作的最小執行流,如果說qq是乙個程序,那麼聊天,發,截圖,加好友這些,都可以算作執行緒。

多執行緒:指在乙個程序下有多個執行緒併發執行。

多執行緒thread類:乙個封裝的類,是.net對執行緒物件的封裝,通過thread類去完成的操作,最終是通過向作業系統請求得到的執行流。

直接**演示一下利用委託aciton開啟多執行緒

action.begininvoke 非同步委託

static

void main(string

args)

private

static

void

asyncmethod1()

private

static

void dosomething(string

name)

console.writeline(

"結束執行緒id:

" + thread.currentthread.managedthreadid.tostring() + "

name:

" +name);

}

執行結果是這樣

可以看到,同步方法,用的是同乙個執行緒 1,而非同步方法,用的是新的執行緒 3,當輸出了「asyncmethod1結束」後,非同步方法才呼叫完成,其實就是用資源換效能。

如果你在非同步**執行時看一下cpu,會發現占用情況比同步方法執行時高多了,但是也不是線性增長的,因為資源總有上限,資源排程也需要成本。

而且非同步方法有個很大的問題就是,不同執行緒的開始和結束是無序的,如果一套順序的業務流程**,用非同步去執行,很可能亂掉,當然這也有解決方法,只是從非同步多執行緒的原理來看,會無法**執行順序。

當我們需要在非同步多執行緒方法中加入日誌,通常不會去把寫日誌的方法加在業務操作的方法中,而是利用**函式,以上例為例。

private

static

void

asyncmethod2()

;action.begininvoke("張三

", asynccallback, "

ok");//

非同步 console.writeline("

asyncmethod2結束執行緒:

" +thread.currentthread.managedthreadid.tostring());

}private

static

void addlog(string

name)

action的begininvoke的第二個和第三個引數分別是,**函式,傳入的引數。

執行結果是這樣

可以看到,主線程1執行完成後就釋放了,執行緒3自己去執行dosomething,並且在執行完後執行addlog,這樣既不會阻塞主線程,又可以監控到非同步方法並寫日誌。

iasyncresult 等待

可以利用begininvoke的返回值進行非同步操作的進度判斷,例如做上傳檔案的進度提示,非同步業務等待提示等等。

改一下asyncmethod2

private

static

void

asyncmethod2()

;iasyncresult asyncresult = action.begininvoke("

張三", asynccallback, "

ok");//

非同步while (!asyncresult.iscompleted)

if(asyncresult.iscompleted)

console.writeline(

"asyncmethod2結束執行緒:

" +thread.currentthread.managedthreadid.tostring());

}

當dosomething方法還沒有執行結束時,迴圈輸出「asyncmenthod2還在非同步呼叫....」,並且休眠100ms,執行完成後輸出「asyncmenthod2非同步呼叫....完成」。

結果是這樣

這裡的問題是, 等待完成的那個while迴圈的內部其實是由主線程1控制的,明顯看到了1和3兩個執行緒並行,直到3執行完1最後才執行完成,中間1其實一直被占用,並且不夠精確,我在迴圈中設定了100ms的延遲,也就是說無論如何也有個100ms的延遲。

訊號量waitone

private

static

void

asyncmethod2()

;iasyncresult asyncresult = action.begininvoke("

張三", asynccallback, "

ok");//

非同步#region 訊號量,精確

//發郵件

//發簡訊

//減庫存

//通知業務人員

asyncresult.asyncwaithandle.waitone();

#endregion

console.writeline(

"asyncmethod2結束執行緒:

" +thread.currentthread.managedthreadid.tostring());

}

這個例子的意思是,當我非同步呼叫dosomething的同時,我需要同時再去呼叫 發郵件,發簡訊等等別的方法,但是呢,我希望後續的方法要等我這個非同步呼叫完成後再執行,於是用asyncresult.asyncwaithandle.waitone()來阻塞當前程序,接受到asyncresult發出的訊號量才繼續。

結果是這樣,可以看到執行緒1是等待dosomething完成後才完成的,而且跟**方法無關,**還是自己跑自己的,可以理解成,非同步方法執行完,執行緒1剩下的**和**方法併發執行。

但是這樣也有個問題,如果非同步方法出了問題,豈不是像同步方法一樣,卡死在這裡?可以給waitone加上引數,讓執行緒1最多阻塞1000ms,1000ms內執行完成,繼續走,沒執行完成,也不管還是繼續走。

asyncresult.asyncwaithandle.waitone(1000);
結果,因為我這個dosomething方法執行時間超過了1000ms,所以可以看到執行緒1等待了1000ms後發現執行緒3的非同步方法還沒執行完,不等了,直接走它的,然後非同步方法執行完成後,再執行**函式。

func 獲得返回值

了解aciton的朋友會知道,action委託沒有返回值,如果需要返回值,可以用func

private

static

void

asyncmethod2()

private

static

string getapi(string

name)

return

"我是api返回的值:

" +name;

}

結果

另外這個返回值也可以放到**中去使用,例如這樣,我改一下func

func func =getapi;

iasyncresult asyncresult = func.begininvoke("

張三", ar =>, "ok

");

結果

看,返回值在**中獲取,是執行緒3,而上例在**外獲取,是執行緒1。

需要注意的是,同乙個委託的begininvoke,只能有乙個endinvoke,你不能呼叫多次,否則報錯。

C 用委託實現非同步,非同步與多執行緒的異同

多執行緒和非同步操作的異同 多執行緒和非同步操作兩者都可以達到避免呼叫執行緒阻塞的目的,從而提高軟體的可響應性。甚至有些時候我們就認為多執行緒和非同步操作是等同的概念。但是,多執行緒和非同步操作還是有一些區別的。而這些區別造成了使用多執行緒和非同步操作的時機的區別。非同步操作的本質 所有的程式最終都...

非同步委託 多執行緒實現搖獎器 winform版

using system using system.collections.generic using system.componentmodel using system.data using system.drawing using system.linq using system.text u...

2014 9 15 非同步委託執行緒高階

昨天悲劇,幫別人調 愣沒調出來。還沒時間寫博文了。憂桑.昨天的今天寫吧,今天也沒學,就上了一天的課 1 首先視窗間資料進行傳遞。也就是父視窗與子視窗資料進行傳遞。用委託實現 在同一命名控制項下定義委託。在子視窗建立委託例項。在父視窗建立子視窗物件,傳遞委託方法。public delegate voi...