Fork me on GitHub
.NET异步

对于异步,相信大家都不十分陌生。准确点来说就是方法执行后立即返回,待到执行完毕会进行通知。就是当一个任务在执行的时候,尤其是需要耗费很长的时间进行处理的任务,如果利用单线程进行操作的话,势必造成界面的阻塞;而利用异步方式,则不会出现这种情况。 区别于同步处理,可以说阻塞的异步其实就相当于同步。

同步方式的实现

先来看一个同步的例子:

假设现在我们需要导入文本文件的内容,然后对文件内容做处理。那么这就需要分为两步来进行,第一步是导入文本内容,我们利用函数A表示;第二部就是处理文本,我们利用函数B来表示。假设现在A不执行完,B不能进行。而且由于文本内容非常大,导入需要十几到几十分钟不等,那么我们得提示用户导入进度,这里就涉及到了界面交互问题。利用同步方式来做,效果如何呢?首先请看运行效果:

其实上面的图片是我运行了一段时间的程序的截图,但是由于作用在了同步模式下,导致界面阻塞,从而产生极差的用户体验。

代码如下:

View Code

那么我们是如何运行的呢:

        #region 开始进行处理
private void btnLoad_Click(object sender, EventArgs e)
{
GetTotalRecordNum(); //得到总条数

ReadIntoMemory();
ProcessRecords();
}
#endregion

看到了没,我们是直接顺序运行的。之所以出现上面的情况,最主要就是界面处理和后台处理均糅合在了同一个线程之中,这样当后台进行数据处理的时候,会造成前台UI线程无法更新UI。要解决这种情况,当然是使用异步方式类处理。

那么在.net编程中,有哪几种模式可以实现异步呢?

4种异步方式

  1. ThreadPool.QueueUserworkItem实现
  2. APM模式(就是BeginXXX和EndXXX成对出现。)
  3. EAP模式(就是Event based, 准确说来就是任务在处理中或者处理完成,会抛出事件)
  4. 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模式的处理方式很明显,Begin×××和End×××成对出现,这种方式使用简便,所以很推荐。并且如果涉及到顺序执行的情况,请参加我的前一篇文章:浅谈C#中常见的委托

然后来说说EAP模式

这种模式也很常见,准确来说就是在系统中通过申明委托事件,然后在执行过程中或者执行完毕后抛出事件。最常见的莫过于WebClient类的DownloadStringCompleted事件,这里我们将使用BackgroundWorker来进行讲解,虽然它本身就能够实现异步操作。在这里,我们只是用到了一个从文本中读取大数据量到内存的操作。图示如下:

这里是进行中的操作:

这里是撤销后的操作:

那么是如何实现的呢?我们先从BackgroundWorker注册的几个事件说起:

首先是DoWork事件,他的注册方式如下:

bgWorker.DoWork += new DoWorkEventHandler(worker_DoWork);

这个主要是用来开启任务的:

 private void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;

ReadIntoMemory(worker, e); //开始工作
}

然后就是ProgressChanged事件,注册方式如下:

         bgWorker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);

从字面上就知道是进行进度报告:

private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pbMain.Value = e.ProgressPercentage; //利用PrograssBar报告导入进度
}

最后就是任务完成报告,注册方式为:

 bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

这里可以进行错误捕获以及任务取消方面的处理:

  private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
tsInfo.Text = "Data Loading Canceled...";
}
else
{
tsInfo.Text = "Data Loading Completed...";
}
}

当然,这个组件在函数运行的过程中,需要向组件传送当前进度的信息,并且在运行过程中,需要检测任务有没有被取消,以达到自动取消任务的功能:

View Code

再说说利用task的实现的方式

 关于Task类,可以说在4.0之前从来没有见过,使用起来非常的简单,也很方便。其实,对于Task类,我也是参考了诸多文章,下面的这句话,引用自另外一篇文章:

Task在并行计算中的作用很凸显,首次构造一个Task对象时,他的状态是Created。以后,当任务启动时,他的状态变成WaitingToRun。Task在一个线程上运行时,他的状态变成Running。任务停止运行,并等待他的任何子任务时,状态变成WaitingForChildrenToComplete。任务完全结束时,它进入以下三个状态之一:RanToCompletion,Canceled或者Faulted。一个Task<TResult>运行完成时,可通过Task<TResult>的Result属性来查询任务的结果,一个Task或者Task<TResult>出错时,可以查询Task的Exception属性来获得任务抛出的未处理的异常,该属性总是返回一个AggregateException对象,他包含所有未处理的异常。
为简化代码,Task提供了几个只读的Boolean属性,IsCanceled,IsFaulted,IsCompleted。注意,当Task处于RanToCompleted,Canceled或者Faulted状态时,IsCompleted返回True。为了判断一个Task是否成功完成,最简单的方法是if(task.Status == TaskStatus.RanToCompletion)。

当然,我们还是以上面的例子来进行编程与讲解。

首先,我们要开启一个Task,那么Task taskOne = new Task(ReadIntoMemory);表示将ReadIntoMemory函数注册成为了任务来运行,然后利用taskOne.Start();来开启任务。那么如何运行第二个任务,并且还要等到第一个运行完成之后呢? 这里我们就需要用到其ContinueWith方法:

Task taskTwo = taskOne.ContinueWith(Action => { ProcessRecords(); });

这样,就行了那么当运行的时候,程序的确会按照顺序来启动任务。图示和APM模式中的图片相同,我就不贴了,下面是代码:

            Task taskOne = new Task(ReadIntoMemory);
taskOne.Start();
Task taskTwo = taskOne.ContinueWith(Action => { ProcessRecords(); });

Task<TResult>泛型方法中的TResult为返回值类型,承载的是一个无参,但是有返回值的任务。所以传入的函数要么是有一个参数带返回值的;要么就是无参数带返回值的,要么就是无参数无返回值的。如果是一个参数,有返回值的话,可以利用下面的方式来进行:

Task<int> taskOne = new Task<int>(a=>ReadIntoMemory((int)a),5);

参考资料

同时大家也可以参看我在StackOverflow中的提问,以期起到抛砖引玉的作用:

参考博客:http://hi.baidu.com/jackeyrain/blog/item/828ec3f70bfa8635730eec0a.html

代码下载

点击这里下载

c#语言学习类

c#语言学习,涵盖学习的基本,中级,高级知识
摘要: 对于异步,相信大家都不十分陌生。准确点来说就是方法执行后立即返回,待到执行完毕会进行通知。就是当一个任务在执行的时候,尤其是需要耗费很长的时间进行处理的任务,如果利用单线程进行操作的话,势必造成界面的阻塞;而利用异步方式,则不会出现这种情况。 区别于同步处理,可以说阻塞的异步其实就相当于同步。阅读全文
posted @ 2012-03-03 16:59 程序诗人 阅读(964) | 评论 (10) 编辑
 
摘要: 错误内容: The type 'System.ServiceProcess.ServiceBase' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. 解决方法: 这是由于没有添加服务引用的关系,请添加对System.ServiceProcess对象的引用即可.阅读全文
posted @ 2012-02-13 15:45 程序诗人 阅读(13) | 评论 (0) 编辑
 
摘要: 一提到委托,浮现在我们脑海中的大概是听的最多的就是类似C++的函数指针吧,呵呵,至少我的第一个反应是这样的。 关于委托的定义和使用,已经有诸多的人讲解过,并且讲解细致入微,尤其是张子阳的那一篇。我就不用多废话了。 今天我要说的是C#中的三种委托方式:Func委托,Action委托,Predicate委托以及这三种委托的常见使用场景。阅读全文
posted @ 2012-01-05 23:27 程序诗人 阅读(2427) | 评论 (12) 编辑
 
摘要: 在开发Asp.net站点的时候,我们会遇到很多的配置参数:网站名称,上传图片后缀,上传文件后缀,关键字过滤,数据库连接字串等等,这些内容如果比较少的话,直接配置到Web.config文件中,借由.NET提供的操作类,将会非常方便的来操作这些自定义配置节点阅读全文
posted @ 2011-12-29 17:59 程序诗人 阅读(122) | 评论 (0) 编辑
 
摘要: 在测试大数据量加载的时候,我们有两件事情需要完成,第一个就是考虑到大数据量,我们得利用异步方式来进行,否则界面及其容易被阻塞住;第二个就是由于数据量过大,导入时间可能比较长,如何通知用户当前导入的进度。阅读全文
posted @ 2011-12-28 19:31 程序诗人 阅读(385) | 评论 (4) 编辑
 
摘要: 软件功能:提供相似结构的文本对比功能,利用异步加载方式支持大数据量导入,同时软件能够自动为导入数据进行行数生成功能,加载完数据之后,可以点击按钮进行数据着色,文本A中的数据在文本B中存在的被着Wheat色,不存在的数据则被着white色;相反,文本B中的数据在文本A中存在的被着YellowGreen色,不存在的数据则被着White色。同时软件支持智能下拉列表查询,数据过滤的功能;并且软件提供了全部数据导出和差异数据导出功能,非常方便。阅读全文
posted @ 2011-12-27 22:13 程序诗人 阅读(324) | 评论 (3) 编辑
 
摘要: Excel can be composed by XML format, using the xml format, you only need to save the xml file with xls entension and it will be opened successfully with EXCEL without any color or font etc. missing !阅读全文
posted @ 2011-12-26 16:33 程序诗人 阅读(63) | 评论 (0) 编辑
 
摘要: 在项目制作的过程中,由于程序需要处理的数据量比较大,所以采用异步的方式来进行,也就是利用委托的BeginInvoke方法和EndInvoke方法来进行。效果很不错,达到了预期。但是由于程序在运行的时候,需要先加载数据,数据加载完成以后,然后进行数据比对差异,并对有差异的数据进行着色处理,在这儿,问题就来了。   什么问题呢?我们知道,当利用异步的时候,实际上系统会自动为我们创建前后台交互线程,那么这个数据加载和差异着色就运行在了这样的线程之上,所以二者的运行先后顺序是不可知的,事实上,程序中着色的混乱也验证了这一点:那就是我虽然原本想让数据加载完成后在进行代码差异着色,可是实际运行的时候发现,数据是边加载边着色的,这也归咎到如何将多个线程合并为一个并且按序运行的问题。阅读全文
posted @ 2011-12-21 20:26 程序诗人 阅读(169) | 评论 (0) 编辑
 
摘要: 首先需要明白的是同步和异步的区别,撇开生硬的定义不谈,就以线程IO请求来说,同步就是让一个线程A去进行IO请求,当请求没有完成之前,线程A一直不离不弃的在那里死等,直到得到请求,可以想象,如果运用同步到请求队列中,这将是一个耗时费力的工作。但是如果采用异步请求的时候,当线程A去进行IO请求的时候,没有得到请求结果之前,线程A可以去做别的事情。这样,利用这种方式,可以提高服务器的吞吐量,MSDN中对此解释如下: 异步操作通常用于执行完成时间可能较长的任务,如打开大文件、连接远程计算机或查询数据库。异步操作在主应用程序线程以外的线程中执行。应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行。阅读全文
posted @ 2011-11-25 17:55 程序诗人 阅读(282) | 评论 (1) 编辑
 
摘要: 如果当一个页面中有大量的控件要涉及到UI交互,并且这些控件需要好多不同的参数,那么我们就不得不为这些控件声明具有不同参数的委托类型,然后再利用InvokeRequired来判断,最后编写世纪操控控件的代码。如果真是这样,那么这个工作量可真的是很大。并且这种Copy/Paste的工作可能让你发疯,重用性太差了,有没有好一点的方法呢?当然有: 通过观察发现,每个控件在进行线程和UI交互的时候,都需要判断以下是否需要进行线程交互(也就是判断是否需要InvokeRequired),那么这个操作能不能集成到一个类中完成呢?阅读全文
posted @ 2011-11-24 18:33 程序诗人 阅读(337) | 评论 (5) 编辑
 
摘要: Service contracts : 定义客户端可以使用哪些服务操作。 Data contracts : 定义服务传输的数据类型。WCF 定义了一些隐式数据契约,像 int、string 等,更多时候我们需要使用 DataContractAttribute 显式定义那些自定义数据结构的数据契约。 Fault contracts : 定义服务引发的错误信息,以及如何传递这些异常给客户端。 Message contracts : 允许我们直接操控服务消息内容和格式,可以是类型化或无类型的。阅读全文
posted @ 2011-11-24 14:10 程序诗人 阅读(69) | 评论 (0) 编辑
 
摘要: 首先说明一下,我这里的异步方式是指获取代码文件的时候,采用的是异步方式,其原因就是我要搜索C:\Program Files文件夹下面的含有关键字为scyGroupBox的代码文件。那么,从我的描述就可以知道,这是一个相当费时的操作,而如果利用程序来遍历这个文件夹,其结果就是将要耗费数秒钟或者更长的时间,并且同步操作会导致界面在搜索完毕后才出来,这样用户就不得不等待几秒钟甚至是数十秒钟,这种体验是相当不友好的。阅读全文
posted @ 2011-11-21 21:37 程序诗人 阅读(195) | 评论 (2) 编辑
 
摘要: 正则表达式默认情况下实现的是最大化匹配,这在有些情况下是非常不愿意出现的,比如下面这段代码:阅读全文
posted @ 2011-11-18 19:49 程序诗人 阅读(187) | 评论 (1) 编辑
 
摘要: 本来是想学习下IHttpAsyncHandler接口的,然后就打开VS2008,快速点击“文件”-->“新建”-->"网站",然后新建一个CometSQL的网站,再在网站下面新建三个类:ProcessAsyncHandler.cs、ProcessAsyncResult.cs、ProcesssMessageHandler.cs,这三个类分别继承自IHttpAsyncHandler、IAsyncResult以及IHttpHandler。本来搞到这儿貌似一切没问题,可是下面调试的时候,麻烦来了阅读全文
posted @ 2011-11-08 23:15 程序诗人 阅读(112) | 评论 (0) 编辑
 
摘要: 一提到正则表达式,相信好多人都不会陌生,并且很多时候,我们都用过,比如说验证邮箱或者是手机号码的正确性等等,在.NET中,提供了强大的正则表达式辅助类,最主要的还是要数Regex类,利用这个类,可以非常方便的来操作正则表达式的匹配工作:阅读全文
posted @ 2011-10-30 17:02 程序诗人 阅读(250) | 评论 (0) 编辑
 
摘要: 本节主要是实现数据库表一对多之间的映射关系。首先,我们需要创建一个Blogs表和一个Posts表,一个Blogs表中可以有多个文章(Posts),典型的一对多的关系:阅读全文
posted @ 2011-10-26 23:12 程序诗人 阅读(110) | 评论 (0) 编辑
 
摘要: 我以前在使用飞鸽传书功能的时候,发现只要打开这个软件,局域网中的用户就会瞬间加载到我的用户列表中,同时在局域网中的用户的列表中马上也会加载我自己的用户信息。而且,飞鸽传书软件没有依靠服务器端的中转,也就是说,完全是客户端的功能。 那么这种机制到底是如何实现的呢?下面来一步一步的剖析。阅读全文
posted @ 2011-10-24 21:16 程序诗人 阅读(1753) | 评论 (14) 编辑
 
摘要: 在C#操作数据库过程中,针对一般的文本控件,比如TextBox,Label等,我们赋值直接使用类似TextBox.Text=****的方式来进行,这种方式从某种意义上来说的确是最简便的方式,但是对于复杂一些的空间,比如说DataGridView,这个时候,绑定数据源我们一般使用DataGridView1.DataSource=****的方式来进行,如果数据源稍微有更改,那么只需要重新调用绑定一遍即可。可以说这种方式是单向的,也即从数据库到UI,但是有没有一种方式能够实现数据源改变的时候,不用重新绑定DataGridView就让它能够自动刷新数据呢,当然,这里要提到的就是DataBinding了。阅读全文
posted @ 2011-10-23 19:59 程序诗人 阅读(1379) | 评论 (11) 编辑
 
摘要: 这里主要来说明ActiveRecord的属性与数据库及其字段的对应关系。 主要以ActiveRecordAttribute、PrimaryKeyAttribute、PropertyAttribute来进行说明。阅读全文
posted @ 2011-10-23 13:03 程序诗人 阅读(109) | 评论 (0) 编辑
 
摘要: 延迟加载,亦称延迟实例化,延迟初始化等,主要表达的思想是,把对象的创建将会延迟到使用时创建,而不是在对象实例化时创建对象,即用时才加载。阅读全文
posted @ 2011-10-15 11:55 程序诗人 阅读(57) | 评论 (0) 编辑
 
摘要: 我以前在使用飞鸽传书功能的时候,发现只要打开这个软件,局域网中的用户就会瞬间加载到我的用户列表中,同时在局域网中的用户的列表中马上也会加载我自己的用户信息。而且,飞鸽传书软件没有依靠服务器端的中转,也就是说,完全是客户端的功能。阅读全文
posted @ 2011-09-18 15:28 程序诗人 阅读(299) | 评论 (7) 编辑
 
摘要: 当我们读取一个大数据量的数据表的时候,如果采用直接读的方式,很容易造成界面成为“白板”的现象,这也是所谓的假死。这种方式并不是十分好,因为它不能让用户非常直观的看到界面(比如加入进度条显示进度),所以需要有一种手段来防止这种现象的发生。在.net中,要实现这种方式很容易,我们只要利用BeginInvoke开启异步操作即可。首先是开始前的准备工作,我们往Person表中插入一百万数据作为测试数据:阅读全文
posted @ 2011-09-13 23:52 程序诗人 阅读(277) | 评论 (1) 编辑
 
摘要: As we know, In asp.net ,we can use web.config to store the configuration for the website.but In WinForm, we can use App.config to function the same function. See below settings:阅读全文
posted @ 2011-09-02 11:46 程序诗人 阅读(98) | 评论 (2) 编辑
 
摘要: 在进行多线程设计过程中,最重要的就是实现线程同步和线程界面交互。如果想实现线程同步,可以通过lock锁来进行;而如果要想线程和界面交互,则需要利用委托来进行。阅读全文
posted @ 2011-08-31 22:50 程序诗人 阅读(228) | 评论 (0) 编辑
 
摘要: 在使用Castle ActiveRecord的时候,需要两种方式来进行初始化,一种就是通过配置文件,另外一种就是将初始配置进行硬编码,写到程序中来。 当然,一般来说,利用配置文件来进行将会大大简化后期维护,我们首先在程序中添加一个App.config的配置文件,记住,一定要将这个配置文件的生成操作设置为“嵌入的资源”才行。否则会提示如学习笔记二中所出现的问题。阅读全文
posted @ 2011-08-30 22:42 程序诗人 阅读(117) | 评论 (0) 编辑
 
摘要: 在进行castle activerecord设计的时候,经常会出现“NHibernate.Cfg.Configuration”的类型初始值设定项引发异常。当时也不知道是怎么回事,反正是弄好了,谁知道第二次修改了一些东西以后,居然又出现了这个错误提示,但是当时就是不知道为什么,摸索了半天,原来是xml嵌入资源的事情。 如果你的项目中有App.config等配置文件,请将其设置为“嵌入的资源”,这样再运行的时候,就不会出错了。阅读全文
posted @ 2011-08-29 23:29 程序诗人 阅读(146) | 评论 (0) 编辑
 
摘要: Castle ActiveRecord抛弃了Nhibernate的繁杂的配置,采用了一种更加方便的方式来组织项目结构,是对Nhibernate的再次封装,大大简化了开发,下面就来说明其配置过程阅读全文
posted @ 2011-08-28 10:51 程序诗人 阅读(167) | 评论 (0) 编辑
 
 
 
posted @ 2011-08-14 22:48 程序诗人 阅读(148) | 评论 (0) 编辑
 
 
posted @ 2011-08-12 10:12 程序诗人 阅读(158) | 评论 (0) 编辑
 
 
摘要: 在C#中,Thread用的是比较多的,至少在windows form中使用是比较频繁的。一说到线程,可能马上就会想到界面和线程交互的头疼事,多线程之前数据共享,线程异步等等。这些当然是比较头疼的,只要有信心 ,慢慢来,相信理解不是难事。阅读全文
posted @ 2011-08-10 21:39 程序诗人 阅读(113) | 评论 (0) 编辑
 
 
posted @ 2011-08-10 00:17 程序诗人 阅读(100) | 评论 (0) 编辑
 
 
posted @ 2011-08-02 21:57 程序诗人 阅读(287) | 评论 (1) 编辑
 
 
 
 
 
 
posted @ 2011-04-24 17:55 程序诗人 阅读(75) | 评论 (0) 编辑
 
 
 
 
 
posted @ 2011-04-11 23:09 程序诗人 阅读(195) | 评论 (0) 编辑
 
摘要: 主要讲解了利用JS来解析DataSet.GetXml()方法产生的XML数据。阅读全文
posted @ 2011-04-07 14:03 程序诗人 阅读(290) | 评论 (0) 编辑
 
摘要: 主要讲解了IHttpCallBackEventHandler的使用方法以及调用的次序,并依据聊天室和构建TreeView来进行演示。阅读全文
posted @ 2011-04-05 14:33 程序诗人 阅读(866) | 评论 (3) 编辑
 
 
摘要: bind() live() delegate()方法备忘阅读全文
posted @ 2011-03-12 23:53 程序诗人 阅读(254) | 评论 (0) 编辑
 
摘要: 主要是讲解了GridView的另外一种绑定方法,可以在数据量大的情况下大大提高响应的速度,记录下来以作备忘。阅读全文
posted @ 2011-03-06 21:58 程序诗人 阅读(390) | 评论 (0) 编辑
 
摘要: C#委托的同步调用、异步调用、异步回调。阅读全文
posted @ 2011-03-05 00:34 程序诗人 阅读(177) | 评论 (1) 编辑
 
摘要: 本例中,主要实现的是向Access数据库中添加记录的功能。其中,主窗体负责显示数据,而弹出的子窗体负责添加数据,数据添加完毕,需要刷新主窗体。阅读全文
posted @ 2011-02-27 18:52 程序诗人 阅读(541) | 评论 (0) 编辑
 
摘要: asp.net下载方面的例子,以便做备忘阅读全文
posted @ 2011-02-19 18:15 程序诗人 阅读(199) | 评论 (0) 编辑
 
摘要: 主要讲解了GridView多表头的制作方式,借以备忘。阅读全文
posted @ 2011-02-13 15:36 程序诗人 阅读(632) | 评论 (0) 编辑
 
摘要: 主要讲解了vsto技术的针对excel的简单应用,希望有用。阅读全文
posted @ 2011-02-11 16:24 程序诗人 阅读(193) | 评论 (0) 编辑
 
摘要: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://jianle.blog.51cto.com/429692/475639阅读全文
posted @ 2011-01-10 13:26 程序诗人 阅读(168) | 评论 (1) 编辑
 
摘要: 主要是讲解了C#操作符重载的一些内容,以便备忘.阅读全文
posted @ 2011-01-07 15:45 程序诗人 阅读(1848) | 评论 (0) 编辑
 
摘要: 主要是gridview中的双dropdownlist联动问题,注意namingContainer的使用方法即可.阅读全文
posted @ 2010-12-30 17:17 程序诗人 阅读(55) | 评论 (0) 编辑
 
摘要: 主要讲解了如何利用IHttpHandler来进行页面处理阅读全文
posted @ 2010-12-30 11:24 程序诗人 阅读(64) | 评论 (0) 编辑
 
摘要: 主要是利用一种非常简便的方法来记忆asp.net的生命周期阅读全文
posted @ 2010-12-11 14:44 程序诗人 阅读(143) | 评论 (0) 编辑
 
摘要: 利用urlrewriter实现伪静态阅读全文
posted @ 2010-11-29 22:07 程序诗人 阅读(98) | 评论 (0) 编辑
 
 
posted @ 2010-11-14 11:41 程序诗人 阅读(65) | 评论 (0) 编辑
 
 
posted @ 2010-11-11 15:17 程序诗人 阅读(38) | 评论 (0) 编辑
 
 
 
 
posted @ 2010-11-06 20:54 程序诗人 阅读(27) | 评论 (0) 编辑
 
 
 
posted @ 2010-10-23 23:57 程序诗人 阅读(370) | 评论 (0) 编辑
 
 
 
 
 
 
 
 
posted @ 2010-09-10 13:26 程序诗人 阅读(138) | 评论 (1) 编辑
 
 
posted @ 2010-09-10 11:13 程序诗人 阅读(485) | 评论 (1) 编辑
 
 
posted @ 2010-09-02 09:26 程序诗人 阅读(27) | 评论 (0) 编辑
 
 
posted @ 2010-09-01 14:47 程序诗人 阅读(61) | 评论 (0) 编辑
 
 
 
posted @ 2010-08-21 17:04 程序诗人 阅读(215) | 评论 (0) 编辑
 
 
posted @ 2010-08-20 10:33 程序诗人 阅读(86) | 评论 (0) 编辑
 
 
 
posted @ 2010-08-12 17:53 程序诗人 阅读(314) | 评论 (0) 编辑
 
 
posted @ 2010-08-11 09:36 程序诗人 阅读(96) | 评论 (1) 编辑
 
 
posted @ 2010-08-10 18:22 程序诗人 阅读(209) | 评论 (0) 编辑
 
 
 
posted @ 2010-08-09 18:57 程序诗人 阅读(218) | 评论 (0) 编辑
 
 
posted @ 2010-07-29 19:44 程序诗人 阅读(187) | 评论 (0) 编辑


posted on 2012-03-03 22:27  HackerVirus  阅读(696)  评论(0编辑  收藏  举报