您的位置:首页 > 编程语言 > C#

C#读取文件的实时进度条

2016-07-18 11:49 302 查看

C#读取文件的实时进度条

对线程及其线程间通讯,线程访问UI控件的问题没有任何经验,通过编写读取文件的实时进度条来增加一些此方面的基础知识。

目的

写过一个用Redis存取数据的小项目,Redis的持久化机制导致在机器crash掉的时候可能会丢失数据,项目也有把检测到的数据写入txt的需求,由于数据txt写入是实时的(每获取一条记录,就写入一条),所以机器crash掉的时候,数据的恢复可以通过读取生成的txt文件来恢复到数据库。由于数据比较多,等待过程漫长,为了增加用户体验以及跟踪实时进度,于是自己想写一个实时进度条。

待解决问题

进度条的总进度的获取

如何获取当前读取的进度

进度条实时更新

用多线程解决单线程操作UI页面卡顿问题

思路

进度条的总进度有两种定义:总进度为txt文本文件的行数(数据都是按照行写入),文本文件的大小。如果用文本文件的行数来定义总进度,会导致要通过代码获取文本文件的总行数,计算行数与读取+存储Redis用到了完全相同的代码,这样导致了两次完全相同文件读取,牺牲了一半的效率。通过计算文本文件的大小来定义总长度,每次在读取到一条数据是计算出数据占文本文件大小的百分比,就得到了本次读取的进度。

.NET禁止了跨线程调用控件,要通过UI对象的invoke方法,反射调用UI控件的方法。

通过线程间接更改UI控件,UI控件就不会卡顿未响应

ManualResetEvent eventX = new ManualResetEvent(false);//控制线程状态
//获取文件大小
private long len;
private long redlen;
//获取文件大小(多个文件)
private void readFile()
{
DirectoryInfo di = new DirectoryInfo(restoreFilePath);
foreach (FileInfo fi in di.GetFiles())
{
len += fi.Length;
}
string s = (len / 32).ToString();
}
//从线程池取线程,用该线程读取文件并存储到redis,直至文件读取完毕,退出线程
public void circleRead()
{
//files是一个存储txt文件路径的列表
fs = new FileStream(files[index], FileMode.Open);
sr = new StreamReader(fs);
readFile();
eventX.WaitOne();
while (index < fileCount)
{
eventX.Reset();
ThreadPool.QueueUserWorkItem(new WaitCallback(changeUIPGBar),new object());
eventX.WaitOne();//直到接收到Set通知,否则阻塞线程
}
this.Invoke(new updateLbl(updateState),new object[]{"导入完成"});
}

private void button2_Click(object sender, EventArgs e)
{
//启动一个线程去执行循环读取的线程,异步更新UI界面,这样就不会出现UI线程卡顿
Thread t = new Thread(circleRead);
t.IsBackground = true;
t.Start();
}


比较重要的方法和数名已经在代码中作出注解

关于后台更新UI线程控件与卡顿问题将会再调查,调查完毕会写博客论述
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C# ui 线程