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

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

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值