汕头企业网站怎么做,遵义网络推广软文,用wordpress搭建商店,专业柳州网站建设价格前文写了关于C#中的异步编程。后台有无数人在讨论#xff0c;很多人把异步和多线程混了。文章在这儿#xff1a;一文说通C#中的异步编程所以#xff0c;本文从体系的角度#xff0c;再写一下这个异步编程。一、C#中的异步编程演变1. 异步编程模型这是C#中早期的异步模型很多人把异步和多线程混了。文章在这儿一文说通C#中的异步编程所以本文从体系的角度再写一下这个异步编程。 一、C#中的异步编程演变1. 异步编程模型这是C#中早期的异步模型通过IAsyncResult接口来实现。实现的代码大体是这个样子class MyClass
{IAsyncResult BeginAction(para ..., AsyncCallback callback, object state);T EndAction(IAsyncResult async_result);
}
这种方式在一些库里还有保留像FileSteam类里的BeginRead和EndRead方法组就是这种方式。编程时不建议用这种方式。2. 基于事件的异步模型这是C#中间一个过渡时期的异步模型核心是基于一个或多个事件、事件处理委托的派生类型是一种使用多线程的模式。这个模式在类库里多用在Winform/WPF中的组件的事件处理你可以随便拿一个Framework 4.5以前的组件去研究大多数都是这种方式。这种方式的实现大体是这个样子class MyClass
{void ActionAsync(para ...);event ActionCompletedEventHandler action_completed;
}
这种方式使用多线程所以它具有多线程的全部特点和要求。从微软的建议来看Framework 4.5以后并不推荐使用这种模式。3. 基于任务的异步模型这种异步模型从Framework 4.0以后引入使用单一方法来表示异步的开始和完成。这是目前推荐的异步开发方式。在上个文章中的异步模式就是这个方式。这个方式的代码实现是这样的class MyClass
{TaskT ActionAsync(para ...);
}我们所说的异步包括前文讲的异步全部是基于这个基于任务的异步模型来讨论。在这个模型下前文说过异步不是多线程。今天再强调一遍异步不仅不是多线程同时异步也不一定会使用多线程。二、异步模型中的“任务”先来看看任务Task和TaskT这是异步模型的核心。这个“任务”是一种“承诺”承诺会在稍后完成任务。它有两个关键字async和await。注意是await不是wait。这儿再强调一下Task.Wait是个同步方法用在多线程中等待。Task是Thread的子集因此继承了Wait方法但这个方法不是给异步用的。在某些情况下异步可以采用多线程来实现这时候Task.Wait可以用但这是以多线程的身份来使用的用出问题要查线程而不是异步。关于异步中Task和async、await配合的部分可以去看前一个文章。地址在一文说通C#中的异步编程这儿不再说了。三、异步编程的两种模式1. 单线程模式先看代码Taskstring GetHtmlAsync()
{var client new HttpClient();var gettask client.GetStringAsync(https://home.cnblogs.com/u/tiger-wang);return await gettask;
}
这种模式下这个异步工作于单线程状态。代码虽然返回一个任务TaskT在这个任务依然在主线程中并没有生成一个新的线程。换句话说这种方式不额外占用线程池资源也不需要考虑多线程开发中线程锁定、数据一致性等问题。因为线程没有切换所以也不存在上下文切换的问题。2. 多线程模式既然Task派生自Thread当然也可以用多线程来实现异步。看代码Taskstring GetHtmlAsync()
{var gettask Task.Run(() {var client new HttpClient();return client.GetStringAsync(https://home.cnblogs.com/u/tiger-wang);});return await gettask;
}
对方上一段代码把调用client.GetStringAsync的部分放到了Task.Run里。这种方式中异步被放到了主线程以外的新线程中执行换句话说这个异步在以多线程的方式执行。在这种模式下async和await的配合以及对程序执行次序的控制跟单线程模式是完全一样的。但是要注意前边说了async和await是异步的关键字它不管多线程的事也不会为多线程提供任何保护。多线程中的并发锁、数据锁、上下文切换还需要以多线程的方式另外搞定。Task.Run的内部代码会占用线程池资源并在一个可用的线程上与主线程并行运行。四、异步的两个额外状态1. 取消异步针对的是需要消耗长时间运行的工作。在工作过程中如果需要我们可以取消异步的运行。系统提供了一个类CancellationToken来处理这个工作。定义方式TaskT ActionAsync(para ..., CancellationToken cancellationtoken);
调用方式CancellationTokenSource source new CancellationTokenSource();
CancellationToken cancel_token source.Token;await ActionAsync(para, cancel_token);
需要取消时source.Cancel();
就可以了。在做API时异步中加个CancellationToken是基本的代码礼节。2. 进度长时间运行如果能给出个进度也不错。定义方式TaskT ActionAsync(para ..., IProgressT progress);
其中T是需要返回的进度值可以是各种需要的类型。当然我们需要实现IProgresspublic class ProgressT : IProgressT
{ public Progress(); public Progress(ActionT handler); protected virtual void OnReport(T value); public event EventHandlerT ProgressChanged;
}
IProgressT通过回调来发送进度值引发捕获并处理。 全文完。 这篇文章是对前一篇文章的补充和扩展。所以要两篇一起看才更好。一文说通C#中的异步编程喜欢就来个三连让更多人因你而受益