❶ 如何正確理解.NET 4.5和C#5.0中的async/await非同步編程模式
使用非同步編程,可以避免性能瓶頸並增強應用程序的總體響應能力。 但是,編寫非同步應用程序的傳統技術可能比較復雜,使它們難以編寫、調試和維護。
C# 中的 async 和 await 關鍵字都是非同步編程的核心。 通過使用這兩個關鍵字,可以使用 .NET framework 或 Windows 運行時中的資源輕松創建非同步方法(幾乎與創建同步方法一樣輕松)。 通過使用被稱為非同步方法的 async 和 await 定義的非同步方法。
特徵:
方法簽名包含一個 Async 或 async 修飾符。
按照約定,非同步方法的名稱以「Async」後綴結尾。
返回類型為下列類型之一:
如果你的方法有操作數為 TResult 類型的返回語句,則為 Task<TResult>。
如果你的方法沒有返回語句或具有沒有操作數的返回語句,則為 Task。
方法通常包含至少一個 await 表達式,該表達式標記一個點,在該點上,直到等待的非同步操作完成方法才能繼續。 同時,將方法掛起,並且控制項返回到方法的調用方。 本主題的下一節將解釋懸掛點發生的情況。
在非同步方法中,可使用提供的關鍵字和類型來指示需要完成的操作,且編譯器會完成其餘操作,其中包括持續跟蹤控制項以掛起方法返回等待點時發生的情況。 一些常規流程(例如,循環和異常處理)在傳統非同步代碼中處理起來可能很困難。 在非同步方法中,元素的編寫頻率與同步解決方案相同且此問題得到解決。
❷ 什麼是同步編程、非同步編程
同步編程:傳統的同步編程是一種請求響應模型,調用一個方法,等待其響應返回。就是一個線程獲得了一個任務,然後去執行這個任務, 當這個任務執行完畢後,才能執行接下來的另外一個任務。
非同步編程:非同步編程就是要重新考慮是否需要響應的問題,也就是縮小需要響應的地方。因為越快獲得響應,就是越同步化,順序化,事務化,性能差化,非同步編程通常是通過fire and forget方式實現。
(2)非同步編程模式擴展閱讀:
在同步編程中,所有的操作都是順序執行的,比如從socket中讀取(請求),然後寫入(回應)到socket中,每一個操作都是阻塞的。
非同步編程的原則是,讓進程處理多個並發執行的上下文來模擬並行處理方式 ,非同步應用使用一個事件循環,當一個事件觸發暫停或恢復執行上下文:
只有一個上下文處於活動狀態,上下文之間進行輪替,代碼中的顯示指令告訴事件循環,哪裡可以暫停執行,這時,進程將查找其他待處理的線程進行恢復,最終,進程將回到函數暫停的地方繼續運行,從一個執行上下文移到另一個上下文稱為切換。
❸ java 非同步編程
用非同步輸入輸出流編寫Socket進程通信程序
在Merlin中加入了用於實現非同步輸入輸出機制的應用程序介麵包:java.nio(新的輸入輸出包,定義了很多基本類型緩沖(Buffer)),java.nio.channels(通道及選擇器等,用於非同步輸入輸出),java.nio.charset(字元的編碼解碼)。通道(Channel)首先在選擇器(Selector)中注冊自己感興趣的事件,當相應的事件發生時,選擇器便通過選擇鍵(SelectionKey)通知已注冊的通道。然後通道將需要處理的信息,通過緩沖(Buffer)打包,編碼/解碼,完成輸入輸出控制。
通道介紹:
這里主要介紹ServerSocketChannel和 SocketChannel.它們都是可選擇的(selectable)通道,分別可以工作在同步和非同步兩種方式下(注意,這里的可選擇不是指可以選擇兩種工作方式,而是指可以有選擇的注冊自己感興趣的事件)。可以用channel.configureBlocking(Boolean )來設置其工作方式。與以前版本的API相比較,ServerSocketChannel就相當於ServerSocket(ServerSocketChannel封裝了ServerSocket),而SocketChannel就相當於Socket(SocketChannel封裝了Socket)。當通道工作在同步方式時,編程方法與以前的基本相似,這里主要介紹非同步工作方式。
所謂非同步輸入輸出機制,是指在進行輸入輸出處理時,不必等到輸入輸出處理完畢才返回。所以非同步的同義語是非阻塞(None Blocking)。在伺服器端,ServerSocketChannel通過靜態函數open()返回一個實例serverChl。然後該通道調用serverChl.socket().bind()綁定到伺服器某埠,並調用register(Selector sel, SelectionKey.OP_ACCEPT)注冊OP_ACCEPT事件到一個選擇器中(ServerSocketChannel只可以注冊OP_ACCEPT事件)。當有客戶請求連接時,選擇器就會通知該通道有客戶連接請求,就可以進行相應的輸入輸出控制了;在客戶端,clientChl實例注冊自己感興趣的事件後(可以是OP_CONNECT,OP_READ,OP_WRITE的組合),調用clientChl.connect(InetSocketAddress )連接伺服器然後進行相應處理。注意,這里的連接是非同步的,即會立即返回而繼續執行後面的代碼。
選擇器和選擇鍵介紹:
選擇器(Selector)的作用是:將通道感興趣的事件放入隊列中,而不是馬上提交給應用程序,等已注冊的通道自己來請求處理這些事件。換句話說,就是選擇器將會隨時報告已經准備好了的通道,而且是按照先進先出的順序。那麼,選擇器是通過什麼來報告的呢?選擇鍵(SelectionKey)。選擇鍵的作用就是表明哪個通道已經做好了准備,准備干什麼。你也許馬上會想到,那一定是已注冊的通道感興趣的事件。不錯,例如對於伺服器端serverChl來說,可以調用key.isAcceptable()來通知serverChl有客戶端連接請求。相應的函數還有:SelectionKey.isReadable(),SelectionKey.isWritable()。一般的,在一個循環中輪詢感興趣的事件(具體可參照下面的代碼)。如果選擇器中尚無通道已注冊事件發生,調用Selector.select()將阻塞,直到有事件發生為止。另外,可以調用selectNow()或者select(long timeout)。前者立即返回,沒有事件時返回0值;後者等待timeout時間後返回。一個選擇器最多可以同時被63個通道一起注冊使用。
應用實例:
下面是用非同步輸入輸出機制實現的客戶/伺服器實常式序――程序清單1(限於篇幅,只給出了伺服器端實現,讀者可以參照著實現客戶端代碼):
程序類圖
public class NBlockingServer {
int port = 8000;
int BUFFERSIZE = 1024;
Selector selector = null;
ServerSocketChannel serverChannel = null;
HashMap clientChannelMap = null;//用來存放每一個客戶連接對應的套接字和通道
public NBlockingServer( int port ) {
this.clientChannelMap = new HashMap();
this.port = port;
}
public void initialize() throws IOException {
//初始化,分別實例化一個選擇器,一個伺服器端可選擇通道
this.selector = Selector.open();
this.serverChannel = ServerSocketChannel.open();
this.serverChannel.configureBlocking(false);
InetAddress localhost = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(localhost, this.port );
this.serverChannel.socket().bind(isa);//將該套接字綁定到伺服器某一可用埠
}
//結束時釋放資源
public void finalize() throws IOException {
this.serverChannel.close();
this.selector.close();
}
//將讀入位元組緩沖的信息解碼
public String decode( ByteBuffer byteBuffer ) throws
CharacterCodingException {
Charset charset = Charset.forName( "ISO-8859-1" );
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode( byteBuffer );
String result = charBuffer.toString();
return result;
}
//監聽埠,當通道准備好時進行相應操作
public void portListening() throws IOException, InterruptedException {
//伺服器端通道注冊OP_ACCEPT事件
SelectionKey acceptKey =this.serverChannel.register( this.selector,
SelectionKey.OP_ACCEPT );
//當有已注冊的事件發生時,select()返回值將大於0
while (acceptKey.selector().select() > 0 ) {
System.out.println("event happened");
//取得所有已經准備好的所有選擇鍵
Set readyKeys = this.selector.selectedKeys();
//使用迭代器對選擇鍵進行輪詢
Iterator i = readyKeys.iterator();
while (i
else if ( key.isReadable() ) {//如果是通道讀准備好事件
System.out.println("Readable");
//取得選擇鍵對應的通道和套接字
SelectableChannel nextReady =
(SelectableChannel) key.channel();
Socket socket = (Socket) key.attachment();
//處理該事件,處理方法已封裝在類ClientChInstance中
this.readFromChannel( socket.getChannel(),
(ClientChInstance)
this.clientChannelMap.get( socket ) );
}
else if ( key.isWritable() ) {//如果是通道寫准備好事件
System.out.println("writeable");
//取得套接字後處理,方法同上
Socket socket = (Socket) key.attachment();
SocketChannel channel = (SocketChannel)
socket.getChannel();
this.writeToChannel( channel,"This is from server!");
}
}
}
}
//對通道的寫操作
public void writeToChannel( SocketChannel channel, String message )
throws IOException {
ByteBuffer buf = ByteBuffer.wrap( message.getBytes() );
int nbytes = channel.write( buf );
}
//對通道的讀操作
public void readFromChannel( SocketChannel channel, ClientChInstance clientInstance )
throws IOException, InterruptedException {
ByteBuffer byteBuffer = ByteBuffer.allocate( BUFFERSIZE );
int nbytes = channel.read( byteBuffer );
byteBuffer.flip();
String result = this.decode( byteBuffer );
//當客戶端發出」@exit」退出命令時,關閉其通道
if ( result.indexOf( "@exit" ) >= 0 ) {
channel.close();
}
else {
clientInstance.append( result.toString() );
//讀入一行完畢,執行相應操作
if ( result.indexOf( "\n" ) >= 0 ){
System.out.println("client input"+result);
clientInstance.execute();
}
}
}
//該類封裝了怎樣對客戶端的通道進行操作,具體實現可以通過重載execute()方法
public class ClientChInstance {
SocketChannel channel;
StringBuffer buffer=new StringBuffer();
public ClientChInstance( SocketChannel channel ) {
this.channel = channel;
}
public void execute() throws IOException {
String message = "This is response after reading from channel!";
writeToChannel( this.channel, message );
buffer = new StringBuffer();
}
//當一行沒有結束時,將當前字竄置於緩沖尾
public void append( String values ) {
buffer.append( values );
}
}
//主程序
public static void main( String[] args ) {
NBlockingServer nbServer = new NBlockingServer(8000);
try {
nbServer.initialize();
} catch ( Exception e ) {
e.printStackTrace();
System.exit( -1 );
}
try {
nbServer.portListening();
}
catch ( Exception e ) {
e.printStackTrace();
}
}
}
程序清單1
小結:
從以上程序段可以看出,伺服器端沒有引入多餘線程就完成了多客戶的客戶/伺服器模式。該程序中使用了回調模式(CALLBACK)。需要注意的是,請不要將原來的輸入輸出包與新加入的輸入輸出包混用,因為出於一些原因的考慮,這兩個包並不兼容。即使用通道時請使用緩沖完成輸入輸出控制。該程序在Windows2000,J2SE1.4下,用telnet測試成功。
❹ Java非同步編程可以嗎
不論是伺服器端編程還是客戶端編程,編程中的同步和非同步對程序員來說都應該不陌生,我們經常會用同步編程來解決順序執行問題、用非同步解決並行執行問題。然而,就是這樣的常見的編程模式,有人卻將其申請為專利。在谷歌專利查詢網站上專利公開號為US 20140282625 A1的專利內容就是Asynchronous programming model for concurrent workflow scenarios,在這個專利的內容摘要描述有:
非同步方式在編程中的執行過程是:先將包含有跟流程信息相關的全局變數和全局上下文指針存儲到一個上下文結構體中。當非同步函數被執行時,全局上下文指針被存儲到本地變數中,當函數執行完,全局上下文指針可以從本地變數中恢復。
下面的流程圖和組件圖可看出這個專利中含蓋的編程模式和架構。
圖1
圖2
專利是一把雙刃劍,它能保護專利發明人的權利、鼓勵更多人來發明創造,但也會因此限制其推廣和普遍使用、浪費生產力。UNIX 和 BSD 的專利之爭就是最惡劣的一個案例,Java 和安卓之爭也給業界帶來了很多的麻煩。2004 年 4 月,微軟公司申請到一個專利,內容是計算機上,在一個特定時間內按下多次按鍵來啟動應用程序,即微軟為雙擊滑鼠啟動程序申請了專利。幸好微軟沒有動用這項專利,否則的話後果實在太恐怖了。蘋果公司也申請了很多讓人哭笑不得的專利,其中最奇葩的是矩形圓角外觀設計專利。
蘋果此前獲得的諸多關於 iPhone 和 iPad 的專利中或多或少都會包含一些實際的功能,譬如 Home 鍵、背部輪廓設計或者前面板整體玻璃覆蓋設計等。但此次獲得的專利卻單單專注於外觀,蘋果的意圖很簡單:圓角矩形就是蘋果發明的!專利所保護的圓角矩形設計,是一個非常寬泛的概念,寬泛到圖中這個邊框的橫豎線條的比例都能成為它保護的對象,無論設備是 7 寸還是 20 寸。
專利可以用來維護原創者的權益,但是專利的尺度寬泛以及漏洞極有可能通過了一些不實用的專利而引起很多不必要的麻煩,甚至對行業的發展造成阻礙.
❺ 前端開發中如何實現非同步編程
非同步編程其實很常見,特別是在出線Node.js之後,非同步編程更是讓很多開發者受益。那麼回到最初的地方,傳統的前端開發中如何實現非同步編程呢?下面列舉了js實現非同步編程的四種方式。
方法一:使用回調函數
方法二:事件監聽
可以定義一個事件,並為這個事件設定處理函數。這樣只有當這個時間發生的情況下,對應的處理函數才會被執行。
方法三:事件的發布/訂閱
這個模式在NodeJS以及其他JS框架中都有實現,是一個非常常用的非同步編程方式。具體的原理及實現方法可以參考我之前的博客:http://blog.csdn.net/fareise/article/details/52198877《 Node中EventEmitter以及如何實現JavaScript中的訂閱/發布模式》,裡面有比較詳細的解析。
方法四:Promise模式
ES6中提供了原生的Promise對象,這個模式最開始只是一個構想,後來由一些框架庫實現。Promise對象代表了未來才會知道結果的事件。
Promise的基本思路就是,將需要非同步執行的事件儲存起來,然後根據非同步事件之行後的結果狀態執行下一步的操作。具體的Promise對象的原理和ES6中的使用方法將在下一篇文章中更加深入的進行介紹。
❻ C#幾種非同步編程
1、非同步編程模型 (APM) 模式(也稱為 IAsyncResult 模式),其中非同步操作要求 Begin 和 End 方法(例如,非同步寫操作的 BeginWrite 和 EndWrite)。對於新的開發工作不再建議採用此模式。
2、基於事件的非同步模式 (EAP) 需要一個具有 Async 後綴的方法,還需要一個或多個事件、事件處理程序、委託類型和 EventArg 派生的類型。EAP 是在 .NET Framework 2.0 版中引入的。對於新的開發工作不再建議採用此模式。
3、基於任務的非同步模式 (TAP),該模式使用一個方法表示非同步操作的啟動和完成。.NET Framework 4 中引入了 TAP,並且是 .NET Framework 中非同步編程的建議方
❼ C#如何使用非同步編程
C#非同步方法:提供了一種簡便方式完成可能需要長時間運行的工作,而不必阻止調用方的線程。非同步方法的調用方可以繼續工作,而不必等待非同步方法完成。
代碼實現過程:
///<summary>
///非同步方法,解決長等待問題
///</summary>
///<paramname="action"></param>
///<paramname="entity"></param>
///<returns></returns>
publicasyncTaskAsyncAdd(Func<FAQ_Info,VMessage>fun,FAQ_Infoentity)
{
returnSystem.Threading.Tasks.Task.Run(()=>
//解決UI阻塞,這種並不是真正的並行執行,而是開了一個新線程非同步執行代碼段
//主UI不會等待它返回結果的,如果要與主線程合作開發,即並行開發,需要加await來獲取Task的返回結果
{
fun(entity);
});
}
非同步的三種模式:
1.等待模式,在發起了非同步方法以及做了一些其它處理之後,原始線程就中斷,並且等待非同步方法完成之後再繼續。
2.輪詢模式,原始線程定期檢查發起的線程是否完成,如果沒有則可以繼續做一些其它的事情。
3.回調模式,原始線程一直在執行,無需等待或檢查發起的線程是否完成。在發起的線程中的引用方法完成之後,發起的線程就會調用回調方法,由回調方法在調用EndInvoke之前處理非同步方法的結構。
❽ 什麼是非同步編程
傳統的同步編程是一種請求響應模型,調用一個方法,等待其響應返回.
非同步編程就是要重新考慮是否需要響應的問題,也就是縮小需要響應的地方。因為越快獲得響應,就是越同步化,順序化,事務化,性能差化。
非同步編程通常是通過fire and forget方式實現,發射事件後即忘記,做別的事情了,無需立即等待剛才發射的響應結果了。(發射事件的地方稱為生產者,而將在另外一個地方響應事件的處理者稱為消費者).非同步編程是一種事件驅動編程,需要完全改變思路,將「請求響應」的思路轉變到「事件驅動」思路上,是一種軟體編程思維的轉變.下面幾種你看參考一下
1、非同步編程模型 (APM) 模式(也稱為 IAsyncResult 模式),其中非同步操作要求 Begin 和 End 方法(例如,非同步寫操作的 BeginWrite 和 EndWrite)。對於新的開發工作不再建議採用此模式。
2、基於事件的非同步模式 (EAP) 需要一個具有 Async 後綴的方法,還需要一個或多個事件、事件處理程序、委託類型和 EventArg 派生的類型。EAP 是在 .NET Framework 2.0 版中引入的。對於新的開發工作不再建議採用此模式。
3、基於任務的非同步模式 (TAP),該模式使用一個方法表示非同步操作的啟動和完成。.NET Framework 4 中引入了 TAP,並且是 .NET Framework 中非同步編程的建議方法。
❾ 下面哪些方法可以用作javascript非同步模式的編程
javascript語言是單線程機制。所謂單線程就是按次序執行,執行完一個任務再執行下一個。
對於瀏覽器來說,也就是無法在渲染頁面的同時執行代碼。
單線程機制的優點在於實現起來較為簡單,運行環境相對簡單。缺點在於,如果中間有任務需要響應時間過長,經常會導致
頁面載入錯誤或者瀏覽器無響應的狀況。這就是所謂的逗同步模式地,程序執行順序與任務排列順序一致。對於瀏覽器來說,
同步模式效率較低,耗時長的任務都應該使用非同步模式;而在伺服器端,非同步模式則是唯一的模式,如果採用同步模式個人認為
伺服器很快就會出現12306在高峰期的表現。。。。
非同步模式的四種方式:
1.回調函數callback
所謂回調函數,就是將函數作為參數傳到需要回調的函數內部再執行。
典型的例子就是發送ajax請求。例如:
$.ajax({
async: false,
cache: false,
dataType: 'json',
url: "url",
success: function(data) {
console.log('success');
},
error: function(data) {
console.log('error');
}
})
當發送ajax請求後,等待回應的過程不會堵塞程序運行,耗時的操作相當於延後執行。
回調函數的優點在於簡單,容易理解,但是可讀性較差,耦合度較高,不易於維護。
2.事件驅動
javascript可以稱之為是基於對象的語言,而基於對象的基本特徵就是事件驅動(Event-Driven)。
事件驅動,指的是由滑鼠和熱鍵的動作引發的一連串的程序操作。
例如,為頁面上的某個
$('#btn').onclick(function(){
console.log('click button');
});
綁定事件相當於在元素上進行監聽,是否執行注冊的事件代碼取決於事件是否發生。
優點在於容易理解,一個元素上可以綁定多個事件,有利於實現模塊化;但是缺點在於稱為事件驅動的模型後,流程不清晰。
3.發布/訂閱
發布訂閱模式(publish-subscribe pattern)又稱為觀察者模式(Observer pattern)。
該模式中,有兩類對象:觀察者和目標對象。目標對象中存在著一份觀察者的列表,當目標對象
的狀態發生改變時,主動通知觀察者,從而建立一種發布/訂閱的關系。
jquery有相關的插件,在這不是重點不細說了。。。。回頭寫個實現貼上來
4.promise模式
promise對象是CommonJS工作組提供的一種規范,用於非同步編程的統一介面。
promise對象通常實現一種then的方法,用來在注冊狀態發生改變時作為對應的回調函數。
promise模式在任何時刻都處於以下三種狀態之一:未完成(unfulfilled)、已完成(resolved)和拒絕(rejected)。以CommonJS
Promise/A
標准為例,promise對象上的then方法負責添加針對已完成和拒絕狀態下的處理函數。then方法會返回另一個promise對象,以便於形成promise管道,這種返回promise對象的方式能夠支持開發人員把非同步操作串聯起來,如then(resolvedHandler,
rejectedHandler); 。resolvedHandler
回調函數在promise對象進入完成狀態時會觸發,並傳遞結果;rejectedHandler函數會在拒絕狀態下調用。
Jquery在1.5的版本中引入了一個新的概念叫Deferred,就是CommonJS promise A標準的一種衍生。可以在jQuery中創建
$.Deferref的對象。同時也對發送ajax請求以及數據類型有了新的修改,參考JQuery API。
除了以上四種,javascript中還可以利用各種函數模擬非同步方式,更有詭異的諸如用同步調用非同步的case
只能用team里同事形容java和javascript的一句話作為結尾:
逗寫java像在高速路上開車,寫javascript像在草原上開車地-------------以此來形容javascript這種無類型的語言有多自由
but,如果草原上都是坑。
❿ 怎樣使用 async amp;await 一步步將同步代碼轉換為非同步編程
相對於之前Begin/End模式和事件模式,async/await模式讓程序員得以用同步的代碼結構進行非同步編程。async/await入門很方便,但是深入理解卻涉及很多領域,如線程池、同步上下文等等。我斷斷續續接觸了幾個月,稍微有一些心得: await的作用是等待