基礎概念
程序:程式執行時,佔據的計算資源的合集,稱為程序,如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,會發現占用情況比同步方法執行時高多了,但是也不是線性增長的,因為資源總有上限,資源排程也需要成本。
而且非同步方法有個很大的問題就是,不同執行緒的開始和結束是無序的,如果一套順序的業務流程**,用非同步去執行,很可能亂掉,當然這也有解決方法,只是從非同步多執行緒的原理來看,會無法**執行順序。
當我們需要在非同步多執行緒方法中加入日誌,通常不會去把寫日誌的方法加在業務操作的方法中,而是利用**函式,以上例為例。
privateaction的begininvoke的第二個和第三個引數分別是,**函式,傳入的引數。static
void
asyncmethod2()
;action.begininvoke("張三
", asynccallback, "
ok");//
非同步 console.writeline("
asyncmethod2結束執行緒:
" +thread.currentthread.managedthreadid.tostring());
}private
static
void addlog(string
name)
執行結果是這樣
可以看到,主線程1執行完成後就釋放了,執行緒3自己去執行dosomething,並且在執行完後執行addlog,這樣既不會阻塞主線程,又可以監控到非同步方法並寫日誌。
iasyncresult 等待
可以利用begininvoke的返回值進行非同步操作的進度判斷,例如做上傳檔案的進度提示,非同步業務等待提示等等。
改一下asyncmethod2
private當dosomething方法還沒有執行結束時,迴圈輸出「asyncmenthod2還在非同步呼叫....」,並且休眠100ms,執行完成後輸出「asyncmenthod2非同步呼叫....完成」。static
void
asyncmethod2()
;iasyncresult asyncresult = action.begininvoke("
張三", asynccallback, "
ok");//
非同步while (!asyncresult.iscompleted)
if(asyncresult.iscompleted)
console.writeline(
"asyncmethod2結束執行緒:
" +thread.currentthread.managedthreadid.tostring());
}
結果是這樣
這裡的問題是, 等待完成的那個while迴圈的內部其實是由主線程1控制的,明顯看到了1和3兩個執行緒並行,直到3執行完1最後才執行完成,中間1其實一直被占用,並且不夠精確,我在迴圈中設定了100ms的延遲,也就是說無論如何也有個100ms的延遲。
訊號量waitone
private這個例子的意思是,當我非同步呼叫dosomething的同時,我需要同時再去呼叫 發郵件,發簡訊等等別的方法,但是呢,我希望後續的方法要等我這個非同步呼叫完成後再執行,於是用asyncresult.asyncwaithandle.waitone()來阻塞當前程序,接受到asyncresult發出的訊號量才繼續。static
void
asyncmethod2()
;iasyncresult asyncresult = action.begininvoke("
張三", asynccallback, "
ok");//
非同步#region 訊號量,精確
//發郵件
//發簡訊
//減庫存
//通知業務人員
asyncresult.asyncwaithandle.waitone();
#endregion
console.writeline(
"asyncmethod2結束執行緒:
" +thread.currentthread.managedthreadid.tostring());
}
結果是這樣,可以看到執行緒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...