加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

用Timer还是用BackgroundWorker实现定时更新画面的功能

发布时间:2021-05-20 14:32:57 所属栏目:大数据 来源: https://blog.csdn.net/kasama1
导读:用Timer还是用BackgroundWorker实现定时更新画面的功能 标签:?timerobjectrandomstring工作class 2010-02-10 17:47 ? 974人阅读 ? 评论(0) ? 收藏 ? 举报 版权声明:本文为博主原创文章,未经博主允许不得转载。 第一次发文章,水平有限,如有错误欢迎大家

用Timer还是用BackgroundWorker实现定时更新画面的功能

标签:?timerobjectrandomstring工作class ? 974人阅读? 评论(0)? 收藏? 举报

第一次发文章,水平有限,如有错误欢迎大家指出。

?

声明:

1,测试环境为vs2008,?.net framework 3.5

2,此次我使用的Timer是?System.Windows.Forms 命名空间下的 Timer 组件,另外两个Timer我没试验。

3,我没有用工具箱添加Timer和BackgroundWorker

?

首先

介绍一下画面

总共有3个Form

主画面

?

点击第一个图标弹出下面的画面

?

Timer画面

?

点击第二个图标弹出下面的画面

?

BackgroundWorker

?

?

两个画面很类似。

实现的是同一个功能。

?

主画面功能不详述。

?

先说第一个画面

?

[c-sharp]? view plain ?copy
  1. using?System;??
  2. using?System.Windows.Forms;??
  3. namespace?TimerAndWorker??
  4. {??
  5. ????///?<summary>??
  6. ????///?System.Windows.Forms.Timer示例??
  7. ///?运行时会出现画面假死??
  8. ///?</summary>??
  9. ????public?partial?class?FrmTimer?:?Form??
  10. ????{??
  11. ????????public?FrmTimer()??
  12. ????????{??
  13. ????????????InitializeComponent();??
  14. ????????}??
  15. ????????#region?"变量定义"??
  16. ????????private?System.Windows.Forms.Timer?timer;??
  17. ????????Random?rd;??
  18. ????????#endregion??
  19. ????????#region?"Timer相关的内容"??
  20. ????????///?<summary>??
  21. ????????///?初始化Timer??
  22. private?void?InitTimer()??
  23. ????????????Console.WriteLine("进入?InitTimer");??
  24. ????????????this.timer?=?new?System.Windows.Forms.Timer();??
  25. ????????????this.timer.Interval?=?5000;??
  26. this.timer.Tick?+=?new?System.EventHandler(this.timer1_Tick);??
  27. this.timer.Start();??
  28. ????????????Console.WriteLine("走出?InitTimer");??
  29. ????????}??
  30. ///?Timer每隔一定时间将会让画面执行一次这个方法??
  31. ///?<param?name="sender"></param>??
  32. ///?<param?name="e"></param>??
  33. void?timer1_Tick(object?sender,?EventArgs?e)??
  34. ????????????Console.WriteLine("进入?timer1_Tick");??
  35. this.UseWaitCursor?=?true;??
  36. ????????????//?假设这个时候有比较耽误时间的操作??
  37. ????????????//?此处我用Sleep来代替??
  38. ????????????Console.WriteLine("开始忙碌");??
  39. //?画面将会出现假死现象??
  40. ????????????System.Threading.Thread.Sleep(3000);??
  41. ????????????Console.WriteLine("停止忙碌");??
  42. foreach?(DataGridViewRow?row?in?dataGridView1.Rows)??
  43. ????????????{??
  44. ????????????????if?(rd.Next(1,?100)?%?2?==?0)??
  45. ????????????????{??
  46. ????????????????????row.Cells["columnStatus"].Value?=?"连接";??
  47. ????????????????}??
  48. else??
  49. ????????????????????row.Cells["columnStatus"].Value?=?"断开";??
  50. ????????????}??
  51. false;??
  52. ????????????Console.WriteLine("走出?timer1_Tick");??
  53. ????????#endregion??
  54. ????????#region?"与Form有关的内容"??
  55. //?定义了一个产生随机数的对象??
  56. //?目的是为了随机生成画面上的状态??
  57. ??
  58. ///?Form的Load事件??
  59. void?FrmTimer_Load( ????????????Console.WriteLine("进入?FrmTimer_Load");??
  60. ????????????InitDataGridView();??
  61. ????????????InitTimer();??
  62. //?给随机数一个种子??
  63. ????????????rd?=?new?Random(DateTime.Now.Millisecond);??
  64. ????????????Console.WriteLine("走出?FrmTimer_Load");??
  65. ///?给画面上的DataGridView赋初值??
  66. void?InitDataGridView()??
  67. ????????????Console.WriteLine("进入?InitDataGridView");??
  68. for?(Int32?i?=?1;?i?<?6;?i++)??
  69. ????????????{??
  70. ????????????????dataGridView1.Rows.Add(new?String[]?{?"192.168.1."?+?i.ToString(),?"断开"?});??
  71. ????????????Console.WriteLine("走出?InitDataGridView");??
  72. ///?关闭画面??
  73. void?btnClose_Click( ????????????Console.WriteLine("进入?btnClose_Click");??
  74. this.Close();??
  75. ????????????Console.WriteLine("走出?btnClose_Click");??
  76. ///?画面关闭时??
  77. ///?</summary>??
  78. ///?<param?name="sender"></param>??
  79. ///?<param?name="e"></param>??
  80. void?FrmTimer_FormClosing( ????????{??
  81. ????????????Console.WriteLine("进入?FrmTimer_FormClosing");??
  82. ????????????timer.Stop();??
  83. ????????????Console.WriteLine("走出?FrmTimer_FormClosing");??
  84. ???
  85. ????}??
  86. }??
?

?

利用Timer的实现机制实际上是事件(event)机制

?

this.timer.Tick += new System.EventHandler(this.timer1_Tick);

这一行代码是让Timer在指定时间触发一个事件

而画面定义一个方法

private void timer1_Tick(object sender,EventArgs e)

对此事件进行响应。

?

此响应方法是Form的线程去执行的方法,所以,在此方法内执行很耗时的操作时。画面将会出现假死现象。

?

例如:读数据库或者进行网络连接以及复杂运算等等。

本例采用

System.Threading.Thread.Sleep(3000);

来代替耗时操作。实际运行时出现画面没响应的现象,具体现象请下载代码实践一下。

以下是执行时输出的日志

?

copy
    进入?FrmTimer_Load??
  1. 进入?InitDataGridView??
  2. 走出?InitDataGridView??
  3. 进入?InitTimer??
  4. 走出?InitTimer??
  5. 走出?FrmTimer_Load??
  6. 进入?timer1_Tick??
  7. 开始忙碌??
  8. 停止忙碌??
  9. 走出?timer1_Tick??
  10. 进入?btnClose_Click??
  11. 进入?FrmTimer_FormClosing??
  12. 走出?FrmTimer_FormClosing??
  13. 走出?btnClose_Click??
?

?

在每次出现?“开始忙碌” 的时候画面开始假死,鼠标点击画面没反应。停止忙碌时恢复。

?

?

我们再来看看BackgroundWorker的表现

?

代码如下

?

[c-sharp] view plain copy
    using?System.ComponentModel;??
  1. using?System.Windows.Forms;??
  2. namespace?TimerAndWorker??
  3. {??
  4. ///?BackgroundWorker示例??
  5. ///?运行时不会出现画面假死??
  6. ????class?FrmWorker?:?Form??
  7. ????{??
  8. public?FrmWorker()??
  9. ????????????InitializeComponent();??
  10. ????????#region?"Worker"??
  11. //?定义一个BackgroundWorker??
  12. ????????BackgroundWorker?worker;??
  13. ///?初始化worker??
  14. void?InitWorker()??
  15. ????????????Console.WriteLine("进入?InitWorker");??
  16. //?实例化??
  17. ????????????worker?=?new?BackgroundWorker();??
  18. //?给worker指派他要干的活??
  19. ????????????worker.DoWork?+=?new?DoWorkEventHandler(worker_DoWork);??
  20. ??????????????
  21. //?给worker添加回调??
  22. ????????????worker.RunWorkerCompleted?+=?new?RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);??
  23. ??????????????
  24. //?让worker支持取消??
  25. ????????????worker.WorkerSupportsCancellation?=?//?让worker去干活??
  26. ????????????worker.RunWorkerAsync();??
  27. ????????????Console.WriteLine("走出?InitWorker");??
  28. ///?Worker工作完成时的回调函数??
  29. void?worker_RunWorkerCompleted( ????????????Console.WriteLine("进入?worker_RunWorkerCompleted");??
  30. //?当worker结束的时候就是画面停止刷新的时候??
  31. //?所以worker结束时关闭画面??
  32. this.Close();??
  33. ????????????Console.WriteLine("走出?worker_RunWorkerCompleted");??
  34. ///?Worker要干的工作??
  35. void?worker_DoWork( ????????????Console.WriteLine("进入?worker_DoWork");??
  36. while?((sender?as?BackgroundWorker).CancellationPending?==?false)??
  37. ????????????????//?假设这里是很漫长的工作??
  38. ????????????????Console.WriteLine("开始忙碌");??
  39. //?这里并不会出现画面的假死??
  40. ????????????????System.Threading.Thread.Sleep(3000);??
  41. ????????????????Console.WriteLine("停止忙碌");??
  42. ????????????????//?更改画面状态??
  43. ????????????????in?dataGridView1.Rows)??
  44. ????????????????{??
  45. ???????????????????? ????????????????????{??
  46. ????????????????????????row.Cells["columnStatus"].Value?=?"连接";??
  47. ????????????????????}??
  48. else??
  49. ????????????????????????row.Cells["columnStatus"].Value?=?"断开";??
  50. ????????????Console.WriteLine("走出?worker_DoWork");??
  51. ????????#region?"与Form有关的内容"??
  52. //?定义了一个产生随机数的对象??
  53. //?目的是为了随机生成画面上的状态??
  54. ????????Random?rd;??
  55. void?FrmWorker_Load( ????????????Console.WriteLine("进入?FrmWorker_Load");??
  56. ????????????InitWorker();??
  57. ????????????Console.WriteLine("走出?FrmWorker_Load");??
  58. ///?点击关闭按钮时候??
  59. //?让worker取消当前任务??
  60. //?worker结束时就会关画面??
  61. ????????????worker.CancelAsync();??
  62. true;??
  63. this.Visible?=?void?FrmWorker_FormClosing( ????????????Console.WriteLine("进入?FrmWorker_FormClosing");??
  64. if?(worker.IsBusy)??
  65. //?如果worker正在忙则应该取消本次关闭画面的动作??
  66. ????????????????e.Cancel?=?//?等待worker关闭当前画面??
  67. ????????????????worker.CancelAsync();??
  68. false;??????????????????
  69. ????????????}??
  70. ????????????Console.WriteLine("走出?FrmWorker_FormClosing");??
  71. }??

?

由于backgroundworker是后台线程,所以不会出现画面假死现象。即便是

耗时操作

System.Threading.Thread.Sleep(3000);

也不会假死

所以。我建议如果有类似功能要实现的朋友要优先选择BackgroundWorker

这样可以让你的程序界面更灵活。

?

?

?

顺便提一句

====================================================================

以下的文字全是个人理解,很有可能与事实有偏差,欢迎指正。

====================================================================

如果说Form是一个线程,BackgroundWorker是另外一个线程。Form中的控件有可能会被禁止在BackgroundWorker的

Dowork中调用,这种调用被称为跨线程调用。如果出现这样的问题。请尝试下面的方法。

?

DataGridView.CheckForIllegalCrossThreadCalls = true;

?

DataGridView这里用的是类名而不是对象的引用

?

CheckForIllegalCrossThreadCalls?是 Control 类的成员

?

?

Control.?CheckForIllegalCrossThreadCalls

MSDN上的说明是:获取或设置一个值,该值指示是否捕获对错误线程的调用,这些调用在调试应用程序时访问控件的?Handle?属性。

?

?

改变CheckForIllegalCrossThreadCalls 的值,则可以让控件可以被跨线程操作。

?

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读