C#窗体假死的解决方案!急!

时间:2022-08-29 13:45:14
C#做的一个Form窗体,里面的一个按钮,实现的功能:从本地EXCEL读取数据(10W-50W行)到dataTable中,
相关代码: 
 string str = "Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source =" + GetNames.path + ";Extended Properties=Excel 8.0";
            OleDbConnection cnn = new OleDbConnection(str);
            cnn.Open();
     
            string s1 = "select * from [" + GetNames.shName + "$]";
            OleDbDataAdapter oda = new OleDbDataAdapter(s1, cnn);
            dt = new DataTable();
            oda.Fill(dt);
在程序执行过程中,窗体处于假死状态,用户体验很不好。
 如果使用BackGroundWorker,虽然能解决假死,但感觉效率明显慢了很多。请教各位,有没有什么好的办法,改善这个功能??
 关于BackGroundWorker代码
        //1.预览
        private void buttonX1_Click(object sender, EventArgs e)
        {
            backgroundWorker2.RunWorkerAsync();
     
        }
        DataTable dt;
        //2.
        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
                      string str = "Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source =" + GetNames.path + ";Extended Properties=Excel 8.0";
            OleDbConnection cnn = new OleDbConnection(str);
            cnn.Open();
     
            string s1 = "select * from [" + GetNames.shName + "$]";
            OleDbDataAdapter oda = new OleDbDataAdapter(s1, cnn);
            dt = new DataTable();
            oda.Fill(dt);
        }
        //3.
        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           this.dataGridViewX2.DataSource =dt;

        }

 着急,在线等待。先给100分

35 个解决方案

#1


用异步或是工作线程来提取数据,同时启动滚动条或是进度一类的。

#2


怎么会效率很低呢,感觉上应该差不多,界面出个提示,这样有好些,告诉用户等待,后台连接(不用异步也一样),总之就是让用户知道你在干嘛,不要界面一片白,不用异步,一样可以弹出个等待提示

#3


用ThreadPool,线程开多些。

#4


你看看数据量小一点 是否会假死!就搞几百条数据先试试。

#5


引用 4 楼 luodayoudianzi 的回复:
你看看数据量小一点 是否会假死!就搞几百条数据先试试。



数据量小点的,执行时间很短,就没有这个问题了

#6


引用 2 楼 bdmh 的回复:
怎么会效率很低呢,感觉上应该差不多,界面出个提示,这样有好些,告诉用户等待,后台连接(不用异步也一样),总之就是让用户知道你在干嘛,不要界面一片白,不用异步,一样可以弹出个等待提示


我拿5w行数据跑了下,一次性全部读取。不用异步,大概要5s,如果用了上面的BackGroudWorker,居然要等16s左右才出来结果,虽然解决了窗体假死问题

#7


假死应该是这个数据库里数据量挺大吧。用多线程会好一点。
弄个进度条出来告诉用户正在工作中,用户交互体验会好

#8


基本代码就是上面的那些,请各位老师完善,我来测试,并回帖各版测试结果

#9


放在 线程里执行 ,或者 给 用户 一个提示

#10


怎么会这么悲剧啊,只要一开线程,速度下降明显,继续等待解决方案

#11


该回复于2013-10-29 09:25:07被管理员删除

#13


使用多线程的Task类,使用dataTable的beginxxx异步方法

#14


数据量大就弄进度条吧

#15


引用 5 楼 zxbqqx 的回复:
Quote: 引用 4 楼 luodayoudianzi 的回复:

你看看数据量小一点 是否会假死!就搞几百条数据先试试。



数据量小点的,执行时间很短,就没有这个问题了

这个读取数据有批量读取或存储的你找找看,以前搞过!

#16


我们遇到处理大量数据的时候考虑微软自带的批量处理 ,又或者分批的处理!

#17


引用 6 楼 zxbqqx 的回复:
Quote: 引用 2 楼 bdmh 的回复:

怎么会效率很低呢,感觉上应该差不多,界面出个提示,这样有好些,告诉用户等待,后台连接(不用异步也一样),总之就是让用户知道你在干嘛,不要界面一片白,不用异步,一样可以弹出个等待提示


我拿5w行数据跑了下,一次性全部读取。不用异步,大概要5s,如果用了上面的BackGroudWorker,居然要等16s左右才出来结果,虽然解决了窗体假死问题


真是奇怪,为什么会有这么大的差别。

#18


我的想法是...你预估一下1W行要多少时间,10W行要多少时间. 
读取之前提示用户需要多少秒就行了. EXCEL装5W行可以10W行没必要哇.何况50W行,你想下用户用这个是来干什么的,到底是不是真的有必要都显示出来.

#19


我感觉,显示10W这么多数据是没什么压力的,不显示也可以,那个dataGridView可以不要,但必须要读到dataTable,然后还要对这些数据进行关键词筛选。
现在的问题是读到dataTable,在UI里肯定会造成界面假死,在其他线程里,速度又变慢。是方法问题吗?代码都在上面

#20


用多线程可以吗?

#21


分页读取,分页加载。
一次获取50万条数据,本来就不合理,毕竟界面上又不能同时显示50万条。

#22


为什么要一次读取50w条?

#23


用后台线程就行,再加一个进度控件就好了
我认为不会存在速度差异,无法理解LZ的测试结果

#24


加个菊花让用户看看

#25


如果只是为了显示,而不是为了马上计算,可以先 select top 10000条出来,放在table1,然后再用BackGroudWorker来select所有,这样可以在短时间内取出足够用户查看的数据.
就是和上面有提到的分页类似的效果

#26


如果只是读取数据的话,甭用那个gridview了,用listview单独写个线程一条一条的把数据插进去,用不了多少多长时间,最起码画面不会卡死,用户会看到那个竖排滚动条在一直缩小,也知道数据在一点一点往里加

#27


@25楼  取出来的目的就是立即就行关键词处理,处理时间也不会短,用户希望在处理这个任务时,他们能够忽略这个窗体,去做其他事情,类似于360下载时,在右下角有个小气泡的任务。

#28


用多线程啊,开一个线程专门来读取Excel

#29


一次性在更新界面数据过多,你用什么异步,线程,都没办法解决!!
解决方法
线程中读取部分数据比如100条,或则弄个双缓冲,更新界面,到底部再加载下100条

#30


多线程+进度条

#31


引用 27 楼 zxbqqx 的回复:
@25楼  取出来的目的就是立即就行关键词处理,处理时间也不会短,用户希望在处理这个任务时,他们能够忽略这个窗体,去做其他事情,类似于360下载时,在右下角有个小气泡的任务。

实际情况说不定就如你说的会变慢.
既然这样子,是不是可以换一种方案来做,先通过程序把excel的数据导入到access中,但后在access中做处理,然后取出结果?
也可以用更高效一点的单机版数据库sqlite来配合

#32


用回调吧,一下就好了。很好用的,如果需要资料我可以发给你哦

#33


为什么要一次性获取完所有数据呢.分页分批次后台线程获取不更合理吗?

#34


看看!不懂。

#35


@ 所有人  
   渴望各位老师提供帮助,最好能发点资料给俺学习下,
QQ 703585987

#1


用异步或是工作线程来提取数据,同时启动滚动条或是进度一类的。

#2


怎么会效率很低呢,感觉上应该差不多,界面出个提示,这样有好些,告诉用户等待,后台连接(不用异步也一样),总之就是让用户知道你在干嘛,不要界面一片白,不用异步,一样可以弹出个等待提示

#3


用ThreadPool,线程开多些。

#4


你看看数据量小一点 是否会假死!就搞几百条数据先试试。

#5


引用 4 楼 luodayoudianzi 的回复:
你看看数据量小一点 是否会假死!就搞几百条数据先试试。



数据量小点的,执行时间很短,就没有这个问题了

#6


引用 2 楼 bdmh 的回复:
怎么会效率很低呢,感觉上应该差不多,界面出个提示,这样有好些,告诉用户等待,后台连接(不用异步也一样),总之就是让用户知道你在干嘛,不要界面一片白,不用异步,一样可以弹出个等待提示


我拿5w行数据跑了下,一次性全部读取。不用异步,大概要5s,如果用了上面的BackGroudWorker,居然要等16s左右才出来结果,虽然解决了窗体假死问题

#7


假死应该是这个数据库里数据量挺大吧。用多线程会好一点。
弄个进度条出来告诉用户正在工作中,用户交互体验会好

#8


基本代码就是上面的那些,请各位老师完善,我来测试,并回帖各版测试结果

#9


放在 线程里执行 ,或者 给 用户 一个提示

#10


怎么会这么悲剧啊,只要一开线程,速度下降明显,继续等待解决方案

#11


该回复于2013-10-29 09:25:07被管理员删除

#12


#13


使用多线程的Task类,使用dataTable的beginxxx异步方法

#14


数据量大就弄进度条吧

#15


引用 5 楼 zxbqqx 的回复:
Quote: 引用 4 楼 luodayoudianzi 的回复:

你看看数据量小一点 是否会假死!就搞几百条数据先试试。



数据量小点的,执行时间很短,就没有这个问题了

这个读取数据有批量读取或存储的你找找看,以前搞过!

#16


我们遇到处理大量数据的时候考虑微软自带的批量处理 ,又或者分批的处理!

#17


引用 6 楼 zxbqqx 的回复:
Quote: 引用 2 楼 bdmh 的回复:

怎么会效率很低呢,感觉上应该差不多,界面出个提示,这样有好些,告诉用户等待,后台连接(不用异步也一样),总之就是让用户知道你在干嘛,不要界面一片白,不用异步,一样可以弹出个等待提示


我拿5w行数据跑了下,一次性全部读取。不用异步,大概要5s,如果用了上面的BackGroudWorker,居然要等16s左右才出来结果,虽然解决了窗体假死问题


真是奇怪,为什么会有这么大的差别。

#18


我的想法是...你预估一下1W行要多少时间,10W行要多少时间. 
读取之前提示用户需要多少秒就行了. EXCEL装5W行可以10W行没必要哇.何况50W行,你想下用户用这个是来干什么的,到底是不是真的有必要都显示出来.

#19


我感觉,显示10W这么多数据是没什么压力的,不显示也可以,那个dataGridView可以不要,但必须要读到dataTable,然后还要对这些数据进行关键词筛选。
现在的问题是读到dataTable,在UI里肯定会造成界面假死,在其他线程里,速度又变慢。是方法问题吗?代码都在上面

#20


用多线程可以吗?

#21


分页读取,分页加载。
一次获取50万条数据,本来就不合理,毕竟界面上又不能同时显示50万条。

#22


为什么要一次读取50w条?

#23


用后台线程就行,再加一个进度控件就好了
我认为不会存在速度差异,无法理解LZ的测试结果

#24


加个菊花让用户看看

#25


如果只是为了显示,而不是为了马上计算,可以先 select top 10000条出来,放在table1,然后再用BackGroudWorker来select所有,这样可以在短时间内取出足够用户查看的数据.
就是和上面有提到的分页类似的效果

#26


如果只是读取数据的话,甭用那个gridview了,用listview单独写个线程一条一条的把数据插进去,用不了多少多长时间,最起码画面不会卡死,用户会看到那个竖排滚动条在一直缩小,也知道数据在一点一点往里加

#27


@25楼  取出来的目的就是立即就行关键词处理,处理时间也不会短,用户希望在处理这个任务时,他们能够忽略这个窗体,去做其他事情,类似于360下载时,在右下角有个小气泡的任务。

#28


用多线程啊,开一个线程专门来读取Excel

#29


一次性在更新界面数据过多,你用什么异步,线程,都没办法解决!!
解决方法
线程中读取部分数据比如100条,或则弄个双缓冲,更新界面,到底部再加载下100条

#30


多线程+进度条

#31


引用 27 楼 zxbqqx 的回复:
@25楼  取出来的目的就是立即就行关键词处理,处理时间也不会短,用户希望在处理这个任务时,他们能够忽略这个窗体,去做其他事情,类似于360下载时,在右下角有个小气泡的任务。

实际情况说不定就如你说的会变慢.
既然这样子,是不是可以换一种方案来做,先通过程序把excel的数据导入到access中,但后在access中做处理,然后取出结果?
也可以用更高效一点的单机版数据库sqlite来配合

#32


用回调吧,一下就好了。很好用的,如果需要资料我可以发给你哦

#33


为什么要一次性获取完所有数据呢.分页分批次后台线程获取不更合理吗?

#34


看看!不懂。

#35


@ 所有人  
   渴望各位老师提供帮助,最好能发点资料给俺学习下,
QQ 703585987