关闭

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

标签: C#ui线程
1637人阅读 评论(0) 收藏 举报
分类:

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线程控件与卡顿问题将会再调查,调查完毕会写博客论述

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3762次
    • 积分:122
    • 等级:
    • 排名:千里之外
    • 原创:7篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论