现在的位置: 首页 > 综合 > 正文

使用.NET事件模型通知文件拷贝进度

2013年06月11日 ⁄ 综合 ⁄ 共 6374字 ⁄ 字号 评论关闭


         很久以前看precyboy Blog上的很长一篇文章,讲.NET事件模型的。文章深入浅出,让我受益匪浅,近日想到自己动手熟练熟练。
         于是准备模仿现有的代码写一个使用.NET事件模型通知文件拷贝进度的程序。
         程序效果截图:
            
 
         定义负责完成文件拷贝并报告进度的类CopyReport,该类的对象在完成文件拷贝任务时会触发三个事件,分别是StartCopy、CopyReport 、EndCopy。
        类视图:
        
 
         这里对于初学者来说需要弄懂的“事件”“事件处理程序”的概念。pervyboy的文章解释的很好,这里我就引用他的解释吧:“在面向对象理论中,一个对象(类的实例)可以有属性(property,获取或设置对象的状态)、方法(method,对象可以做的动作)等成员外,还有事件(event)。所谓事件,是对象内部状态发生了某些变化、或者对象做某些动作时(或做之前、做之后),向外界发出的通知。打个比方就是,对象“张三”肚子疼了,然后他站在空地上大叫一声“我肚子疼了!”事件就是这个通知。
         那么,相对于对象内部发出的事件通知,外部环境可能需要应对某些事件的发生,而做出相应的反应。接着上面的比方,张三大叫一声之后,救护车来了把它接到医院(或者疯人院,呵呵,开个玩笑)。外界因应事件发生而做出的反应(具体到程序上,就是针对该事件而写的那些处理代码),称为事件处理程序(event handler)。
         事件处理程序必须和对象的事件挂钩后,才可能会被执行。否则,孤立的事件处理程序不会被执行。另一方面,对象发生事件时,并不一定要有相应的处理程序。就如张三大叫之后,外界环境没有做出任何反应。也就是说,对象的事件和外界对该对象的事件处理之间,并没有必然的联系,需要你去挂接。
         在开始学习之前,我希望大家首先区分“事件”和“事件处理程序”这两个概念。事件是隶属于对象(类)本身的,事件处理程序是外界代码针对对象的事件做出的反应。事件,是对象(类)的设计者、开发者应该完成的;事件处理程序是外界调用方需要完成的。简单的说,事件是“内”;事件处理程序是“外”。”
 
         使用 .NET 事件模型的设计解决了“高耦合”的问题,类CopyReport不会控制Form1的指示进度条,而是通过CopyReport类的事件通知,我们只要挂接我们写好的事件处理程序。这样就实现了进度的指示。

单播和多播
        如果某一事件被挂接多次,则后挂接的事件处理程序,将改写先挂接的事件处理程序。这里就涉及到一个概念,叫“单播事件”。
         所谓单播事件,就是对象(类)发出的事件通知,只能被外界的某一个事件处理程序处理,而不能被多个事件处理程序处理。也就是说,此事件只能被挂接一次,它只能“传播”到一个地方。相对的,就有“多播事件”,对象(类)发出的事件通知,可以同时被外界不同的事件处理程序处理。

CopyReport.cs

using System;
using System.Threading;
using System.Collections;
using System.IO;
using System.Windows.Forms;

namespace Jacky.EventDelegateStudy.FileCopyReport
{
    
/// <summary>
    
/// 文件拷贝进度报告
    
/// </summary>

    public class CopyReport
    
{
        
"事件参数类"

        
//声明委托delegate
        public delegate void StartCopyEventHandler(object sender,StartCopyEventArgs e);
        
public delegate void ReportEventHandler(object sender,ReportEventArgs e);
        
public delegate void EndEventHandler(object sender,EndCopyEventArgs e);

        
// 为每种事件生成一个唯一的键
        static readonly object StartCopyEventKey = new object();
        
static readonly object ReportEventKey = new object();
        
static readonly object EndEventKey = new object();

        
// 为外部挂接的每一个事件处理程序,生成一个唯一的键
        private object EventHandlerKey
        
{
            
get return new object(); }
        }


        
// 为了支持“多播”,这里使用两个 Hashtable:
        
// 一个记录 handlers,
        
// 另一个记录这些 handler 分别对应的 event 类型
        
//(event 的类型用各自不同的 eventKey 来表示)。
        
// 两个 Hashtable 都使用 handlerKey 作为键。

        
"Hashtable存储事件类型和事件处理程序的操作"


        
"使用了 add 和 remove 访问器的事件声明"


        
声明事件调用(虚)函数

抱歉!评论已关闭.