设为首页 加入收藏

TOP

谈谈C#中异步编程模型的变迁
2015-12-01 14:11:46 来源: 作者: 【 】 浏览:13
Tags:谈谈 异步 编程 模型 变迁

大家在编程过程中都会用到一些异步编程的情况。在C#的BCL中,很多api都提供了异步方法,初学者可能对各种不同异步方法的使用感到迷惑,本文主要为大家梳理一下异步方法的变迁以及如何使用异步方法。


在.Net Framework 2.0中,最常见的方法是BeginXXX,和EndXXX这样的方法来搭配使用。这种模式可以概括为方法+回调方法模式或者称为InvokeMethod+EventHandler模式。


这种模型的基本流程是:


我们看一个FileStream的示例方法,在.Net 2.0中,你需要这样使用异步:



using System;


using System.IO;


using System.Text;


?


public class AsyncTest


{


? ? public static void Main(string[] args)


? ? {


? ? ? ? using (FileStream file = new FileStream("Test.txt", FileMode.OpenOrCreate))


? ? ? ? {


? ? ? ? ? ? var bytes = Encoding.UTF8.GetBytes("Test for .net framework 2.0");


?


? ? ? ? ? ? IAsyncResult asyncResult = file.BeginWrite(bytes, 0, bytes.Length, callback, null);


?


? ? ? ? ? ? file.EndWrite(asyncResult);


? ? ? ? }


?


? ? ? ? Console.ReadLine();


? ? }


?


? ? private static void callback(IAsyncResult ar)


? ? {


? ? ? ? Console.WriteLine("Finish Write");


? ? }


}


从.Net 4.0开始,微软引入了Task。由于Task本身的灵活性,也使得我们的异步编程模型更简洁。上面的例子在.Net 4.5中可以这样实现:



using System;


using System.IO;


using System.Text;


using System.Threading.Tasks;


?


public class AsyncTest


{


? ? public static void Main(string[] args)


? ? {


? ? ? ? using (FileStream file = new FileStream("Test.txt", FileMode.OpenOrCreate))


? ? ? ? {


? ? ? ? ? ? var bytes = Encoding.UTF8.GetBytes("Test for .net framework 4.5");


?


? ? ? ? ? ? var task = file.WriteAsync(bytes, 0, bytes.Length);


?


? ? ? ? ? ? task.Wait();


? ? ? ? }


?


? ? ? ? Console.ReadLine();


? ? }


}


为了进一步简化异步模型,微软从Visual Studio 2012开始引入了async和await关键字。这个模型本身是基于编译器的一个语法糖,编译后会生成一个statemachine模型。这样上面例子中的写法也可以简化成:



using System;


using System.IO;


using System.Text;


using System.Threading.Tasks;


?


public class AsyncTest


{


? ? public static void Main(string[] args)


? ? {


? ? ? ? TestFunc();


? ? }


?


? ? private static async void TestFunc()


? ? {


? ? ? ? using (FileStream file = new FileStream("Test.txt", FileMode.OpenOrCreate))


? ? ? ? {


? ? ? ? ? ? var bytes = Encoding.UTF8.GetBytes("Test for .net framework 4.5");


? ? ? ? ? ? await file.WriteAsync(bytes, 0, bytes.Length);


? ? ? ? }


? ? }


}


如果大家注意看BCL中的类库,会发现微软并没有在最新版本的类库中对每一个BeginXXX的方法都添加了XXXAsync方法。这种情况下我们如何能让新的异步模型兼容旧的方法呢?


以NamedPipeServerStream为例,这个类库实现了一个管道的功能,微软并没有为其更新XXXAsync方法,你可以使用TaskFactory来兼容新的异步模型,你可以这样来实现:



private static void OldAsyncModel()


{


? ? NamedPipeServerStream pipe = new NamedPipeServerStream("customPipe", PipeDirection.InOut, -1, PipeTransmissionMode.Message, PipeOptions.Asynchronous | PipeOptions.WriteThrough);


? ? IAsyncResult async = pipe.BeginWaitForConnection(callback, null);


? ? pipe.EndWaitForConnection(async);


}


?


private static async void NewAsyncModel()


{


? ? NamedPipeServerStream pipe = new NamedPipeServerStream("customPipe", PipeDirection.InOut, -1, PipeTransmissionMode.Message, PipeOptions.Asynchronous | PipeOptions.WriteThrough);


?


? ? await Task.Factory.FromAsync(pipe.BeginWaitForConnection, pipe.EndWaitForConnection, null);


}


因此,我们可以总结为,.Net中有两种异步编程模型:


BeginXXX模型微软已经逐渐的考虑废弃,返回Task的异步编程模型目前是微软建议的方式。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇实例探索Class文件 下一篇土耳其屏蔽Reddit

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: