添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  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.     public class Work 
  12.     { 
  13.         Thread thd; 
  14.         private static int count = 0; 
  15.  
  16.         public Work() 
  17.         { 
  18.             thd = new Thread(new ThreadStart(thdDoWork)); 
  19.             thd.Name = "NewThread"
  20.         } 
  21.  
  22.         WarningForm wf;//提示窗体 
  23.         private void thdDoWork()//后台工作 
  24.         { 
  25.             while (true
  26.             { 
  27.                 if ((count++ % 10) == 0) 
  28.                 { 
  29.                     wf = new WarningForm();//创建并显示提示窗体 
  30.                     wf.Show();//将窗体显示为非模式对话框 
  31.                 } 
  32.                 Thread.Sleep(600); 
  33.             } 
  34.         } 
  35.  
  36.         public void ThdStart() 
  37.         {                         
  38.             thd.Start(); 
  39.         } 
  40.     } 
  41. ==========================Work.cs============================== 
  42. 同时呢,在WarningForm的构造函数中添加: 
  43. Console.WriteLine("WarningForm Created in : " + Thread.CurrentThread.Name); 
  44. 这样我们就能够清楚的看到WarningForm是在哪一个线程中被创建显示的。 
  45. Debug,弹出提示窗口,而且后台工作没有停止,但是提示窗口没有响应,后台输出“WarningForm Created in : NewThread”。我分析这是因为我们把提示窗体显示为了非模式的,而后台线程显示窗体后继续执行,并没有维护对提示窗体界面的响应,因此发生了以上现象。 
  46.  
  47. 那我们把"wf.Show()"改为"wf.ShowDialog()"再试一下: 
  48. Debug,弹出提示窗口,界面没有死掉,后台输出"WarningForm Created in : NewThread",但是后台的工作却停止了。这是因为ShowDialog()将窗体显示为模式的,也就是说该窗体的显示阻塞掉了当前线程的运行。 
  49.  
  50. 这样看来,把提示窗体的显示放到后台线程中是不行的,那么,当后台线程需要显示窗体时,如何在主线程中捕获这种消息呢? 
  51. 哈,这位客官运气真好,BackgroundWorker的ReportProgress(int percentProgress, object userState)方法最适合解决这个问题了。我们可以在主线程中注册BackgroundWorker的ProgressChanged事件,当BackgroundWorker的对象调用ReportProgress()时,注册到ProgressChanged事件的方法就会在主线程中执行,对后台线程的运行没有任何影响,然后提示窗体是要显示为模式的还是非模式的就看情况啦! 
  52. 我们修改Work.cs如下: 
  53. ==========================Work.cs============================== 
  54. using System; 
  55. using System.Collections.Generic; 
  56. using System.Linq; 
  57. using System.Text; 
  58. using System.Threading; 
  59. using System.ComponentModel; 
  60.  
  61. namespace ThreadTest 
  62.     public class Work 
  63.     { 
  64.         public BackgroundWorker bg; 
  65.         private static int count = 0; 
  66.  
  67.         public Work() 
  68.         { 
  69.             bg = new BackgroundWorker(); 
  70.         } 
  71.  
  72.         private void bgDoWork(object sender, DoWorkEventArgs e) 
  73.         { 
  74.             Thread.CurrentThread.Name = "BgWorker";//修改后台线程的名字 
  75.             while (true
  76.             { 
  77.                 if ((count++ % 10) == 0) 
  78.                     bg.ReportProgress(count);//激活事件 
  79.                 Thread.Sleep(500); 
  80.             } 
  81.         } 
  82.  
  83.         public void BgStart() 
  84.         { 
  85.             bg.WorkerReportsProgress = true
  86.             bg.DoWork += new DoWorkEventHandler(bgDoWork); 
  87.             bg.RunWorkerAsync(); 
  88.         } 
  89.  
  90.  
  91.     } 
  92. ==========================Work.cs============================== 
  93. 同时在Form1.cs中如下编写: 
  94. ========================Form1.cs片段============================ 
  95.         WarningForm wf; 
  96.         public Form1() 
  97.         { 
  98.             InitializeComponent(); 
  99.             Thread.CurrentThread.Name = "MainThread";//修改主线程名字 
  100.         } 
  101.         private void button3_Click(object sender, EventArgs e) 
  102.         { 
  103.             //work为Work的对象 
  104.             work.bg.ProgressChanged += new ProgressChangedEventHandler(bg_ProgressChanged);//注册这一事件 
  105.             work.BgStart(); 
  106.         } 
  107.  
  108.         private void bg_ProgressChanged(object sender, ProgressChangedEventArgs e) 
  109.         { 
  110.             //事件发生时显示提示窗体 
  111.             wf = new WarningForm(); 
  112.             wf.Show(); 
  113.             //wf.ShowDialog(); 
  114.         } 
  115. ========================Form1.cs片段============================ 
  116. Debug,输出"WarningForm Created in : MainThread",可以看到窗体是在主线程中创建显示的。而无论提示窗体是模式的还是非模式的,一切均能正常运行,到此,我们就实现了要求的功能哈哈! 
  117.  
  118. 另外,请注意ReportProgress(int percentProgress, object userState),它第二个参数是object类型的,再加上如前所述的特性使得BackgroundWorker与界面进行通信的时非常的方便,我们在更新控件的时候可以用它。而如果使用Thread对象的话,则需要通过委托来调用控件的Invoke或者BeginInvoke方法,麻烦的多。但是我想后者肯定具有一些独特的优点,目前我还不知道,求指点。。