.NET 实现异步处理的集中方式
对于异步,相信大家都不十分陌生。准确点来说就是方法执行后立即返回,待到执行完毕会进行通知。就是当一个任务在执行的时候,尤其是需要耗费很长的时间进行处理的任务,如果利用单线程进行操作的话,势必造成界面的阻塞;而利用异步方式,则不会出现这种情况。 区别于同步处理,可以说阻塞的异步其实就相当于同步。
同步方式的实现
先来看一个同步的例子:
假设现在我们需要导入文本文件的内容,然后对文件内容做处理。那么这就需要分为两步来进行,第一步是导入文本内容,我们利用函数A表示;第二部就是处理文本,我们利用函数B来表示。假设现在A不执行完,B不能进行。而且由于文本内容非常大,导入需要十几到几十分钟不等,那么我们得提示用户导入进度,这里就涉及到了界面交互问题。利用同步方式来做,效果如何呢?首先请看运行效果:
#region 第一步:加载进入内存
private void ReadIntoMemory()
{
if (String.IsNullOrEmpty(fileName))
{
MessageBox.Show("文件名不能为空!");
return;
} string result;
long mainCount = ;
using (StreamReader sr = new StreamReader(fileName, Encoding.Default))
{
while ((result = sr.ReadLine()) != null)
{
mainCount++; recordList.Add(result); //添加记录到List中存储,以便在下一步进行处理。 double statusResult = (double)mainCount / (double)totalCount; lblCurrentRecords.Text = mainCount.ToString();
lblStatus.Text = statusResult.ToString("p");
pbMain.Value = Int32.Parse((Math.Floor(statusResult)*).ToString());
}
}
}
#endregion #region 第二步:处理数据
private void ProcessRecords()
{
if (recordList ==null)
{
throw new Exception("数据不存在!");
} if (recordList.Count==)
{
return;
} int childCount = ;
int recordCount = recordList.Count; for (int i = ; i < recordCount; i++)
{
string thisRecord=recordList[i];
if (String.IsNullOrEmpty(thisRecord) || !thisRecord.Contains(","))
{
return;
} string[] result = thisRecord.Split(','); ListViewItem lvi = new ListViewItem(result[]); for (int j = ; j < result.Length; j++)
{
lvi.SubItems.Add(result[j]);
}
listItem.Add(lvi); childCount++;
double percentage = (double)childCount / (double)recordCount;
pbChild.Value = Int32.Parse((Math.Floor(percentage) * ).ToString());
}
}
#endregion
#region 开始进行处理
private void btnLoad_Click(object sender, EventArgs e)
{
GetTotalRecordNum(); //得到总条数 ReadIntoMemory();
ProcessRecords();
}
#endregion
我们是直接顺序运行的。之所以出现上面的情况,最主要就是界面处理和后台处理均糅合在了同一个线程之中,这样当后台进行数据处理的时候,会造成前台UI线程无法更新UI。要解决这种情况,当然是使用异步方式类处理:
那么在.net编程中,有哪几种模式可以实现异步呢?
4种异步方式
- ThreadPool.QueueUserworkItem实现
- APM模式(就是BeginXXX和EndXXX成对出现。)
- EAP模式(就是Event based, 准确说来就是任务在处理中或者处理完成,会抛出事件)
- Task
上面总共4种方式中,其中在.net 2.0中常用的是(1),(2),(3),而在.net 4.0中支持的是(4),注意(4)在.net 2.0中是不能使用的,因为不存在。
首先来说说ThreadPool.QueueUserWorkItem方式,也是最简单的一种方式。
系统将需要运行的任务放到线程池中,那么线程池中的任务就有机会通过并行的方式进行运行。
其次来说说APM模式
这种模式非常常见,当然也是Jeff Richter极力推荐的一种方式。同时我也是这种模式的粉丝。这种模式的使用非常简单,就是利用Begin***的方式将需要进行异步处理的任务放入,然后通过End***的方式来接受方法的返回值。同时在Begin***和End***任务进行的过程中,如果涉及到界面UI的更新的时候,我们完全可以加入通知的功能。
在Begin***和End***进行处理的时候,传递的是IAsyncResult对象,这种对象在Begin***中会承载一个委托对象,然后在End***中进行还原并得到返回值。
如果你在设计的时候,需要有多个方法用到异步,并且想控制他们的运行顺序,请参考ManualResetEvent 和 AutoResetEvent方法,他们均是通过设置信号量来进行同步的。
下面来看一个例子:
假设现在我们需要导入文本文件的内容,然后对文件内容做处理。那么这就需要分为两步来进行,第一步是导入文本内容,我们利用函数A表示;第二部就是处理文本,我们利用函数B来表示。假设现在A不执行完,B不能进行。而且由于文本内容非常大,导入需要十几到几十分钟不等,那么我们得提示用户导入进度,这里就涉及到了界面交互问题。利用APM模式如何来做呢?首先请看运行效果:
#region 典型的APM处理方式,利用Action作为无参无返回值的委托
private void BeginReadIntoMemory()
{
Action action = new Action(ReadIntoMemory);
action.BeginInvoke(new AsyncCallback(EndReadIntoMemory), action);
} private void EndReadIntoMemory(IAsyncResult iar)
{
Action action = (Action)iar.AsyncState;
action.EndInvoke(iar);
} private void BeginProcessRecords()
{
Action action = new Action(ProcessRecords);
action.BeginInvoke(new AsyncCallback(EndProcessRecords), action);
} private void EndProcessRecords(IAsyncResult iar)
{
Action action = (Action)iar.AsyncState;
action.EndInvoke(iar);
}
#endregion
#region 开始进行处理,需要通过ManualResetEvent设置xinhaoilang的方式进行同步
private void btnLoad_Click(object sender, EventArgs e)
{
GetTotalRecordNum(); //得到总条数 BeginReadIntoMemory(); //读取数据到内存
BeginProcessRecords(); //处理数据内容
}
#endregion
在上面的代码段中,APM模式的处理方式很明显
然后来说说EAP模式
这种模式也很常见,准确来说就是在系统中通过申明委托事件,然后在执行过程中或者执行完毕后抛出事件。最常见的莫过于WebClient类的DownloadStringCompleted
事件,这里我们将使用BackgroundWorker来进行讲解,虽然它本身就能够实现异步操作。在这里,我们只是用到了一个从文本中读取大数据量到内存的操作。图示如下:
转自【http://www.cnblogs.com/scy251147/archive/2012/03/03/2378477.html】
.NET 实现异步处理的集中方式的更多相关文章
- 在nginx启动后,如果我们要操作nginx,要怎么做呢 别增加无谓的上下文切换 异步非阻塞的方式来处理请求 worker的个数为cpu的核数 红黑树
nginx平台初探(100%) — Nginx开发从入门到精通 http://ten 众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来 ...
- How to make asynchronous HTTP requests in PHP 4种PHP异步执行的常用方式
[是否等待返回就执行下一步] How to make asynchronous HTTP requests in PHP - Stack Overflow https://stackoverflow. ...
- js 异步加载的方式
js 异步加载的方式 渲染引擎遇到 script 标签会停下来,等到执行完脚本,继续向下渲染 defer 是“渲染完再执行”,async 是“下载完就执行”,defer 如果有多个脚本,会按照在页面中 ...
- 四:SpringBoot-定时任务和异步任务的使用方式
SpringBoot-定时任务和异步任务的使用方式 1.定时任务 2.同步和异步 3.定时器的使用 3.1 定时器执行规则注解 3.2 定义时间打印定时器 3.3 启动类开启定时器注解 4.异步任务 ...
- ajax_异步交互-get/post方式
Ajax的异步交互: 客户端向服务器端发送请求,直到服务器端进行响应,这个过程中,用户可以做任何其他事情(不等). 实现Ajax的异步交互步骤(举例说明): get方式: 1.创建XMLHttpReq ...
- 获取node异步执行结果的方式
拿数据库操作举例: var connection = mysql.createConnection(); connection.query(sql,function(err,rows){xxx} ); ...
- dubbo异步调用三种方式
异步通讯对于服务端响应时间较长的方法是必须的,能够有效地利用客户端的资源,在dubbo中,消费端<dubbp:method>通过 async="true"标识. < ...
- ajax异步请求的常见方式
首先先介绍下ajax,ajax(ASynchronous JavaScript And XML)为异步的javascript和xml.所谓的异步和同步是指: 同步:客户端必须等待服务器的响应,在等待期 ...
- 【JS】370- 总结异步编程的六种方式
点击上方"前端自习课"关注,学习起来~ 作者:Aima https://segmentfault.com/a/1190000019188824 众所周知 JavaScript 是 ...
随机推荐
- 6 高级IO函数
6.1 pipe函数 pipe函数创建一个管道,用于实现进程间通信 #include<unistd.h> ]); 参数包含两个文件描述符fd[0]和fd[1],往fd[1]写入的数据可以从 ...
- Android 4.4 KitKat, the browser and the Chrome WebView
Having V8 as the JavaScript engine for the new web view, the JavaScript performance if much better, ...
- HTML页面加载和解析流程详细介绍
浏览器加载和渲染html的顺序 1. IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的. 2. 在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元 ...
- 安装hbase-0.98.9-hadoop2
1. download http://124.202.164.13/files/1244000005C563FC/www.eu.apache.org/dist/hbase/stable/hbase-0 ...
- leetcode course shedule
题目就不说了,问题本质就是在一个有向图中查找它是不是存在环. 上网百度了一下,方法是,找出图中入度为0 的点,将以它为起点的边去掉. 重复这一动作,直到所有的边都被去掉(没有环)或者存在边但是无法再去 ...
- POJ 1961
#include<iostream> #include<stdio.h> #define MAXN 1000001 using namespace std; char c[MA ...
- NetCore第一步:千里之行 始于环境构筑
今年的6月28号,微软发布了一个正式版本 NetCore.发布的同时,也同时发布了CoreStudio. 这个激动人心的时刻,让跨平台已经不再是什么神话. 让我们一起来开始Core的开发之旅吧. 万事 ...
- Win7系统配置IIS7服务
1.开启IIS7服务 打开控制面板,选择并进入“程序”,双击“打开或关闭Windows服务”,在弹出的窗口中选择“Internet信息服务”下面所有地选项,点击确定后,开始更新服务. 2.安装web文 ...
- EOF的一点注记
int ch; while( (ch = getchar()) != EOF ) { putchar(ch); } 执行程序,输入:we are the,然后回车.运行结果如下: [purple@lo ...
- java控制反转与依赖注入
1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ...