c#中委托、事件和回调

以前写的一个小程序,近来无事改来玩,有一个类执行一些事务性操作,通过winform窗口调用这个类,原来事务类的设计没有事件,在窗口调用时也没有使用多线程,这样就存在几个问题:

1. 事务运行事件长了的话,窗口就会假死,不响应用户的操作;

2. 事务类运行情况窗口不知道,不知道事务究竟执行到什么进度了;

于是就重构代码解决以上问题,第一步改写事务类


    public class clsXUT

    {

        public class Cls_Head

        {

        }


        const int StartIndex = 2244;        //第一份试卷头部的起始位置

        const int HeadLength = 1032;        //头部长度

        const byte DirFlag = 0;

        const byte FileFlag = 1;


        public List Head = new List();

        public event Action progress;      //定义的事件

        public Action p;                  //定义的回调函数,也就是一个没有返回值的委托

        private string xutfn;

        private string outpath;


        public clsXUT(string xutfilepath,string outdir)

        {

            xutfn = xutfilepath;

            outpath = outdir;

        }


        public void run()

        {

            FileStream fs;

            byte[] mmb = Resource1.mmb;

            fs = new FileStream(xutfn, FileMode.Open, FileAccess.Read);

            byte[] buf = new byte[HeadLength];

            while (true)

            {

                //if (progress != null)                                          //如果事件处理程序被绑定

                //    progress(Convert.ToInt32(fs.Position / fs.Length) * 100);  //激发事件

                if (p != null)

                    p(Convert.ToInt32(fs.Position / fs.Length) * 100);            //激发回调函数,函数在用户那里实现

                if (fs.Position >= fs.Length) break;                              //如果到文件结尾则退出

                if (fs.Position == 0) fs.Position = StartIndex;

                fs.Read(buf, 0, buf.Length);

                Head.Add(new Cls_Head(buf));

                Cls_Head head = Head.LastOrDefault();

                if (head.Flag == Cls_Head.FlagType.FileFlag)

                {

                    byte[] data = new byte[head.FileLength];

                    fs.Read(data, 0, data.Length); 

                    FileStream fw = new FileStream(outpath + "\\" + head.Path, FileMode.OpenOrCreate);

                    fw.Write(data, 0, data.Length);       

                    fw.Close();

                }

            }

            fs.Close();

        }


    }


窗口调用代码:

        private void button4_Click(object sender, EventArgs e)

        {

            //以多任务方式来调用事务类

            Task task = new Task(() =>

            {

                string path = textBox2.Text;

                xut = new clsXUT(textBox1.Text, path);               

                xut.progress += Xut_progress;              //使用事件

                xut.p += Xut_progress;                      //使用回调方法

                xut.run();

            });

            task.Start();                                  //启动任务,新版可以使用 dot net4.5使用Task.run(()=>{});

            //亦可使用线程,new Thread(()=>{}).Start()

        }


        private void Xut_progress(int pre)

        {

            if (this.InvokeRequired)

                this.BeginInvoke(new MethodInvoker(() => { progressBar1.Value = pre; }));

                //异步方式更新界面的进度条

        }


通过对比发现事件和回调函数其本质应该是一致的!有空再写个简单的对比程序,编译后看看有啥不同!

你可能感兴趣的:(c#中委托、事件和回调)