以前写的一个小程序,近来无事改来玩,有一个类执行一些事务性操作,通过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
public event Action
public Action
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; }));
//异步方式更新界面的进度条
}
通过对比发现事件和回调函数其本质应该是一致的!有空再写个简单的对比程序,编译后看看有啥不同!