当前位置:编程学习 > C#/ASP.NET >>

C#后台线程工作时更新界面的处理方法

 

1.    需求:后台不间断地进行某种工作,当获得特定结果时弹出窗体进行提示,而工作继续进行。那我的第一反应就是,该工作应放到后台线程中执行,条件满足时创建/显示提示窗体就行啦。代码如下:

2.    ==========================Work.cs==============================

3.    using System;

4.    using System.Collections.Generic;

5.    using System.Linq;

6.    using System.Text;

7.    using System.Threading;

8.    using System.ComponentModel;

9.   

10.   namespace ThreadTest

11.   {

12.       public class Work

13.       {

14.           Thread thd;

15.           private static int count = 0;

16.  

17.           public Work()

18.           {

19.               thd = new Thread(new ThreadStart(thdDoWork));

20.               thd.Name = "NewThread";

21.           }

22.  

23.           WarningForm wf;//提示窗体

24.           private void thdDoWork()//后台工作

25.           {

26.               while (true)

27.               {

28.                   if ((count++ % 10) == 0)

29.                   {

30.                       wf = new WarningForm();//创建并显示提示窗体

31.                       wf.Show();//将窗体显示为非模式对话框

32.                   }

33.                   Thread.Sleep(600);

34.               }

35.           }

36.  

37.           public void ThdStart()

38.           {                        

39.               thd.Start();

40.           }

41.       }

42.   }

43.   ==========================Work.cs==============================

44.   同时呢,在WarningForm的构造函数中添加:

45.   Console.WriteLine("WarningForm Created in : " + Thread.CurrentThread.Name);

46.   这样我们就能够清楚的看到WarningForm是在哪一个线程中被创建显示的。

47.   Debug,弹出提示窗口,而且后台工作没有停止,但是提示窗口没有响应,后台输出“WarningForm Created in : NewThread”。我分析这是因为我们把提示窗体显示为了非模式的,而后台线程显示窗体后继续执行,并没有维护对提示窗体界面的响应,因此发生了以上现象。

48.  

49.   那我们把"wf.Show()"改为"wf.ShowDialog()"再试一下:

50.   Debug,弹出提示窗口,界面没有死掉,后台输出"WarningForm Created in : NewThread",但是后台的工作却停止了。这是因为ShowDialog()将窗体显示为模式的,也就是说该窗体的显示阻塞掉了当前线程的运行。

51.  

52.   这样看来,把提示窗体的显示放到后台线程中是不行的,那么,当后台线程需要显示窗体时,如何在主线程中捕获这种消息呢?

53.   哈,这位客官运气真好,BackgroundWorker的ReportProgress(int percentProgress, object userState)方法最适合解决这个问题了。我们可以在主线程中注册BackgroundWorker的ProgressChanged事件,当BackgroundWorker的对象调用ReportProgress()时,注册到ProgressChanged事件的方法就会在主线程中执行,对后台线程的运行没有任何影响,然后提示窗体是要显示为模式的还是非模式的就看情况啦!

54.   我们修改Work.cs如下:

55.   ==========================Work.cs==============================

56.   using System;

57.   using System.Collections.Generic;

58.   using System.Linq;

59.   using System.Text;

60.   using System.Threading;

61.   using System.ComponentModel;

62.  

63.   namespace ThreadTest

64.   {

65.       public class Work

66.       {

67.           public BackgroundWorker bg;

68.           private static int count = 0;

69.  

70.           public Work()

71.           {

72.               bg = new BackgroundWorker();

73.           }

74.  

75.           private void bgDoWork(object sender, DoWorkEventArgs e)

76.           {

77.               Thread.CurrentThread.Name = "BgWorker";//修改后台线程的名字

78.               while (true)

79.               {

80.                   if ((count++ % 10) == 0)

81.                       bg.ReportProgress(count);//激活事件

82.                   Thread.Sleep(500);

83.               }

84.           }

85.  

86.           public void BgStart()

87.           {

88.               bg.WorkerReportsProgress = true;

89.               bg.DoWork += new DoWorkEventHandler(bgDoW

补充:软件开发 , C# ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,