多线程实现等待屏(欢迎屏)的实现
由于代码生成机器人第一版本中未使用多线程,所以在生成代码或操作过程中经常出现“假死”现象,在第二版本升级中将体验度作为重要指标,所以整个加载过程将实现加载进度显示及进度信息提示。
以下代码参考网友的例子,但网上的例子经过测试问题太多,包括对多线程的处理方面,所以经过改造,实现最终效果,也是最后发布版本所使用的。
特别声明:在多线程调用过程中,尽量不要在构造中使用“CheckForIllegalCrossThreadCalls = false;”,当然对于非常小的工具可以临时使用,在此不主张使用。
1、首先创建WaitFormService.cs类,用于调度等待屏,代码如下:
1 /// <summary> 2 /// 等待窗体的操作服务类 3 /// </summary> 4 public class WaitFormService 5 { 6 private Thread waitThread; 7 private FrmSplash splashForm; 8 private delegate void CloseSplashForm(); 9 private static readonly Object syncLock = new object(); 10 11 private static WaitFormService _instance = null; 12 /// <summary> 13 /// 保证仅有一个实例 14 /// </summary> 15 public static WaitFormService Instance 16 { 17 get 18 { 19 if (WaitFormService._instance == null) 20 { 21 lock (syncLock) 22 { 23 if (WaitFormService._instance == null) 24 { 25 WaitFormService._instance = new WaitFormService(); 26 } 27 } 28 } 29 return WaitFormService._instance; 30 } 31 } 32 33 /// <summary> 34 /// 创建一个等待窗实例 35 /// </summary> 36 public static void CreateWaitForm() 37 { 38 WaitFormService.Instance.CreateForm(); 39 } 40 41 /// <summary> 42 /// 关闭这个等待窗体 43 /// </summary> 44 public static void CloseWaitForm() 45 { 46 WaitFormService.Instance.CloseForm(); 47 } 48 49 /// <summary> 50 /// 设置窗体中的文字内容 51 /// </summary> 52 /// <param name="text"></param> 53 public static void SetWaitFormCaption(string text) 54 { 55 WaitFormService.Instance.SetFormCaption(text); 56 } 57 58 public void CreateForm() 59 { 60 if (waitThread != null) 61 { 62 try 63 { 64 DisposeForm(); //此处实现了委托调用,在创建窗体前检查并释放窗体 65 waitThread.Abort(); 66 waitThread.Join(); 67 waitThread.DisableComObjectEagerCleanup(); 68 } 69 catch { } 70 } 71 72 splashForm = new FrmSplash(); 73 waitThread = new Thread(new ThreadStart(delegate() { 74 Application.Run(splashForm); 75 })); 76 waitThread.Start(); 77 } 78 79 private void DisposeForm() 80 { 81 if (splashForm != null && splashForm.InvokeRequired) 82 { 83 CloseSplashForm csf = new CloseSplashForm(DisposeForm); 84 this.splashForm.Invoke(csf, null); 85 } 86 else 87 { 88 splashForm.Dispose(); 89 } 90 } 91 92 public void CloseForm() 93 { 94 if (waitThread != null) 95 { 96 try 97 { 98 DisposeForm(); 99 waitThread.Abort(); 100 waitThread.Join(); 101 waitThread.DisableComObjectEagerCleanup(); 102 } 103 catch { } 104 } 105 } 106 107 /// <summary> 108 /// 设置等待屏中的显示文字 109 /// </summary> 110 /// <param name="text"></param> 111 public void SetFormCaption(string text) 112 { 113 if (splashForm != null) 114 { 115 try 116 { 117 splashForm.SetText(text); 118 } 119 catch { } 120 } 121 } 122 }
2、必须创建一个等待窗体,并设置显示标签(当然可以再设置进度条等等),我仅实现标签和一个GIF图片,如下图所示:
代码如下:
1 public partial class FrmSplash : Form 2 { 3 public FrmSplash() 4 { 5 InitializeComponent(); 6 } 7 8 private delegate void SetTextHandler(string text); 9 public void SetText(string text) 10 { 11 if (lbl_Status.InvokeRequired) 12 { 13 this.Invoke(new SetTextHandler(SetText), text); 14 } 15 else 16 { 17 this.lbl_Status.Text = text; 18 } 19 } 20 }
3、调用方法,任何时候想要显示信息均调用:WaitFormService.SetWaitFormCaption("执行中,请稍候...");,将“”号中内容换成自己要显示的即可。
说明:不是必须放在try..Catch..finally中,是我因为项目问题才放在这里。
1 try 2 { 3 WaitFormService.CreateWaitForm(); 4 WaitFormService.SetWaitFormCaption("执行中,请稍候..."); 5 //以下为要执行的代码,代码将在主线程执行,同时等待屏将置顶显示并显示设置的内容 6 } 7 catch { } 8 finally 9 { 10 WaitFormService.CloseWaitForm(); 11 }