backgroundWorker加载数据的时候CPU占用过高

浩洁 2014-01-26 02:47:23


private BackgroundWorker search = new BackgroundWorker();
private void searchKey(object sender, EventArgs e)
{
this.listView.Items.Clear();
this.listView.BeginUpdate();
this.search.RunWorkerAsync();
}
private void searchKey(object sender, DoWorkEventArgs e)
{
/*这里是一些查询步骤省略,下面用一个FOR来说明一下我查询到很多结果*/
for(int i=0;i<2000;i++)/*现在我的问题结果数量越大,越会卡的时间长*/
{
string[] list = new string[6];
list[0]="a";
list[1]="b";
list[2]="c";
list[3]="d";
list[4]="e";
list[5]="f";
this.search.ReportProgress(i, list);
}
}
private void search_DoWork(object sender, DoWorkEventArgs e)
{
searchKey(sender, e);
}
private void search_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string[] list = e.UserState as string[];
ListViewItem lv = new ListViewItem(new string[] { list[1], list[2], list[3], list[4] });
lv.ImageKey = list[0];
lv.Tag = list[5];
this.listView.Items.Add(lv);
}
private void search_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.listView.EndUpdate();
}
我的程序结构就是这样的,如果查询的结果数量不多(几十条结果)时,就很快加载完毕,但是结果数量很多(结果数量在几百条)时,就会出现界面卡死,任务管理器显示CPU达到50%,而且要过很久才会加载完毕显示正常。
请问一下是我的结果有问题还是什么情况?
...全文
349 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
浩洁 2014-03-06
  • 打赏
  • 举报
回复
谢谢大家的帮助
erictang2003 2014-01-28
  • 打赏
  • 举报
回复
你还是多在ThreadSleep 上研究一下,尤其是一些还有递归,while(ture)的东西,在多线程执行时非常系统容易假死。
卧_槽 2014-01-27
  • 打赏
  • 举报
回复
2000次循环,每次循环添加一条gridview,每次循环的时间如果比ui线程添加gridview的时间短,那么看起来就和直接从ui界面一气头添加2000条gridview数据的效果是一样的。 ui线程和后台线程就好比,ui是一个工人在刷墙,如果他一直在工作,那么界面就会卡。后台线程就是那个给他提供油漆的人,如果后面那个人没舀一勺子涂料,就要求刷墙的刷一笔,那刷墙的得累死,如果每次倒满一桶再刷一刷子,刷墙工就很轻松,界面就不卡了。 很多人在做程序设计的时候,面临的并不是程序的问题,很多时候都是简单的逻辑问题,初中,小学数学题,这些人大多数时候都是被程序的科技光环蒙蔽的双眼。
zhpfaff 2014-01-27
  • 打赏
  • 举报
回复
用法错误,先循环,每步循环去异步执行 全局量: string[] list = new string[6]; int num = 0; searchKey: for(int i=0;i<2000;i++) { num = i; search.RunWorkerAsync(); } search_DoWork: e.Result = searchKey(search,e); searchKey: list[0]="a"; list[1]="b"; list[2]="c"; list[3]="d"; list[4]="e"; list[5]="f"; return "ok"; RunWorkerCompleted: string rt = e.Result.ToString(); if (e.Error != null) { 错误处理 } else { if (rt == "ok") { 你要更新listView的操作 } else { 错误处理 } }
  • 打赏
  • 举报
回复
不要在 search_ProgressChanged 进行复杂的 UI 操作。如果一定需要显示,那么你可以每100条记录才显示一次,或者没当过了3秒钟才显示。
浩洁 2014-01-26
  • 打赏
  • 举报
回复
引用 6 楼 KarasCanvas 的回复:
其实楼主你这里并不需要报告进度,而且在报告进度的方法里处理数据的做法是不合理的 DoWork方法把所有的数据处理好,然后在RunWorkerCompleted时候更新数据,这时候才使用 BeginUpdate和EndUpdate避免更新的时候控件闪烁
这样的话不是要创建一个公共数组Array?如果数据很大Array体积也越来越大会不会产生资源不足或者什么不利的?
种草德鲁伊 2014-01-26
  • 打赏
  • 举报
回复
这种做法莫名其妙,BackgroundWorker本来已经提供了一个完整的异步处理模型,这里不遵照它的设计,又弄一大堆自己设定的机制,何必还用BackgroundWorker
引用 5 楼 liuchaolin 的回复:
线程操作的关键代码,先将数据保存到全局的DataTable,然后一条条往dataGridView1添加 #region backgroundWorker 将XML导入GridView private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { object[] argumet = (object[])e.Argument; int _rowIndex = int.Parse(argumet[0].ToString()); backgroundWorker1.ReportProgress(_rowIndex); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { dataGridView1.Rows.Add(new object[] { Properties.Resources.PROCESS_READY, e.ProgressPercentage +1 , _dt_am.Rows[e.ProgressPercentage]["Code"], _form_code, "" }); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { _index = _index + 1; if (_index < _dt_am.Rows.Count) { if (_isPlay && !_isStop) { _form_code = _form_code.Substring(0, 10) + (int.Parse(_form_code.Substring(10, 3)) + 1).ToString("D3"); backgroundWorker1.RunWorkerAsync(new object[] { _index }); } } else { bnt_star.Enabled = true; bnt_pause.Enabled = false; bnt_stop.Enabled = false; bnt_update.Enabled = true; mTB_Code.Enabled = true; } if (_isStop) { _index = 0; _updateIndex = 0; } //如果强制关闭 if (_isClose) { this.Close(); } } #endregion
种草德鲁伊 2014-01-26
  • 打赏
  • 举报
回复
楼主
引用 4 楼 mpy2003 的回复:
[quote=引用 3 楼 KarasCanvas 的回复:] 处理的数据多自然就要耗费更多的资源,楼主是在考验我们的智商嘛
没有这种意思,是真心不懂,这个控件的作用不就是另起线程工作,让界面不会“死掉”的么? 另外我自己找资料后有人指出说更新UI速度太快的原因,都在更新UI前加上Thread(10)延时,这样我关注了一下CPU占用率确实能降低,而且睡眠时间越长CPU占用率越低,只是时间总的运行时间更长了并且界面还是一样“死掉”[/quote] 其实楼主你这里并不需要报告进度,而且在报告进度的方法里处理数据的做法是不合理的 DoWork方法把所有的数据处理好,然后在RunWorkerCompleted时候更新数据,这时候才使用 BeginUpdate和EndUpdate避免更新的时候控件闪烁
md5e 2014-01-26
  • 打赏
  • 举报
回复
线程操作的关键代码,先将数据保存到全局的DataTable,然后一条条往dataGridView1添加 #region backgroundWorker 将XML导入GridView private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { object[] argumet = (object[])e.Argument; int _rowIndex = int.Parse(argumet[0].ToString()); backgroundWorker1.ReportProgress(_rowIndex); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { dataGridView1.Rows.Add(new object[] { Properties.Resources.PROCESS_READY, e.ProgressPercentage +1 , _dt_am.Rows[e.ProgressPercentage]["Code"], _form_code, "" }); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { _index = _index + 1; if (_index < _dt_am.Rows.Count) { if (_isPlay && !_isStop) { _form_code = _form_code.Substring(0, 10) + (int.Parse(_form_code.Substring(10, 3)) + 1).ToString("D3"); backgroundWorker1.RunWorkerAsync(new object[] { _index }); } } else { bnt_star.Enabled = true; bnt_pause.Enabled = false; bnt_stop.Enabled = false; bnt_update.Enabled = true; mTB_Code.Enabled = true; } if (_isStop) { _index = 0; _updateIndex = 0; } //如果强制关闭 if (_isClose) { this.Close(); } } #endregion
浩洁 2014-01-26
  • 打赏
  • 举报
回复
引用 3 楼 KarasCanvas 的回复:
处理的数据多自然就要耗费更多的资源,楼主是在考验我们的智商嘛
没有这种意思,是真心不懂,这个控件的作用不就是另起线程工作,让界面不会“死掉”的么? 另外我自己找资料后有人指出说更新UI速度太快的原因,都在更新UI前加上Thread(10)延时,这样我关注了一下CPU占用率确实能降低,而且睡眠时间越长CPU占用率越低,只是时间总的运行时间更长了并且界面还是一样“死掉”
种草德鲁伊 2014-01-26
  • 打赏
  • 举报
回复
处理的数据多自然就要耗费更多的资源,楼主是在考验我们的智商嘛
浩洁 2014-01-26
  • 打赏
  • 举报
回复
引用 1 楼 liuchaolin 的回复:
能否详细点说,因为网上找了很多例子都这样写的
md5e 2014-01-26
  • 打赏
  • 举报
回复
backgroundWorker不是给你这么用的 DoWork一次只执行一条,然后在RunWorkerCompleted中做判断,是否已经执行到2000,如果不到就再DoWork,到了就 结束 意思就是将backgroundWorker看成是一个for循环

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧