❶ 如何正确理解.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的作用是等待