.Net 的异步编程
历史
现在比较流行的异步编程应该是Task模式,这是基于Threadpool线程池实现的更加方便简单的开发模式,但是为了更好理解它的原理,有必要先了解一下它的前辈们。.Net的异步开发基本按照 异步模式->事件驱动->任务驱动 进化的
异步模式
微软为了实现异步开发,在大量的类中加入了以Begin和End为开头的方法。以下代码中,WebRequest类的使用BeginGetResponse方法请求网站信息,EndGetResponse方法则阻塞线程,直到结果返回到ar变量中
private static void AsynchronousPattern()
{
Console.WriteLine(nameof(AsynchronousPattern));
WebRequest request = WebRequest.Create(url);
IAsyncResult result = request.BeginGetResponse(ReadResponse, null);
void ReadResponse(IAsyncResult ar)
{
using (WebResponse response = request.EndGetResponse(ar))
{
Stream stream = response.GetResponseStream();
var reader = new StreamReader(stream);
string content = reader.ReadToEnd();
Console.WriteLine(content.Substring(0, 100));
Console.WriteLine();
}
}
}
如果需要调用用户自定义方法,可以使用代理delegate配合BeginInvoke和EndInvoke方法。代码如下
public delegate string AsyncMethodCaller(int callDuration, out int threadId);
private static void AsyncPattern()
{
AsyncMethodCaller caller= new AsyncMethodCaller(TestAsync);
int threadid=0;
IAsyncResult result = caller.BeginInvoke(3000, out threadid,null, null);
Console.WriteLine("等待异步方法TestAsync执行完成");
string res = caller.EndInvoke(out threadid, result);
Console.WriteLine("Completed!");
}
static string TestAsync(int callDuration, out int threadId)
{
Console.WriteLine("TestAsync");
for (int i = 0; i < 5; i++)
{
Thread.Sleep(callDuration);
Console.WriteLine("TestAsync:" + i.ToString());
}
threadId = Thread.CurrentThread.ManagedThreadId;
return string.Format("");
}
现在这种方法已经被淘汰,只有老项目中还能见到。
基于事件驱动的异步模式
从.Net 2.0开始,基于事件驱动的异步模式,这种模式是调用一个以Async结尾的方法,比如WebClient的DownloadStringAsync方法,当这个方法结束时将触发DownloadStringCompleted事件,用户可以在这个事件中写入自己的需要的东西。
private static void EventBasedAsyncPattern()
{
Console.WriteLine(nameof(EventBasedAsyncPattern));
using (var client = new WebClient())
{
client.DownloadStringCompleted += (sender, e) =>//当DownloadStringAsync返回时触发
{
Console.WriteLine(e.Result.Substring(0, 100));
};
client.DownloadStringAsync(new Uri(url));
Console.WriteLine();
}
}
任务驱动的异步编程
终于到了这篇文章的重头戏,从.NetFrameWork4.0开始,引入了Task类,微软极力推荐使用Task来执行异步任务,现在C#类库中的异步方法基本都用到了Task;net5.0推出了async/await,让异步编程更为方便。
Task是在ThreadPool的基础上推出的,ThreadPool中有若干数量的线程,如果有任务需要处理时,会从线程池中获取一个空闲的线程来执行任务,任务执行完毕后线程不会销毁,而是被线程池回收以供后续任务使用。当线程池中所有的线程都在忙碌时,又有新任务要处理时,线程池才会新建一个线程来处理该任务,如果线程数量达到设置的最大值,任务会排队,等待其他任务释放线程后再执行。线程池能减少线程的创建,节省开销。
530



被折叠的 条评论
为什么被折叠?



