WinForm下的loading框的实现
前言:在项目使用C/S模式情况下,由于需要经常进行数据的刷新,如果直接进行刷新,会有一个等待控件重画的过程,非常的不友好,因此在这里添加一个loading框进行等待显示。
实现:在经过多方面查询资料,终于是实现了一个完整的loading框程序,这里主要解决在多次点击查询按钮或者加载数据时出现的:执行 CreateHandle() 时无法调用值 Close()或者无法访问已释放的对象或者在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。这三个问题困扰我很久,最终通过不断的调试,将其解决,话不多说,直接上代码。
1.下面类为loading框帮助类,在实际调用过程中,使用该类调用相关函数即可。
1 class LoadingHelper 2 { 3 #region 相关变量定义 4 /// <summary> 5 /// 定义委托进行窗口关闭 6 /// </summary> 7 private delegate void CloseDelegate(); 8 private static LoaderForm loadingForm; 9 private static readonly Object syncLock = new Object(); //加锁使用 10 11 #endregion 12 13 private LoadingHelper() 14 { 15 16 } 17 18 /// <summary> 19 /// 显示loading框 20 /// </summary> 21 public static void ShowLoadingScreen() 22 { 23 // Make sure it is only launched once. 24 if (loadingForm != null) 25 return; 26 Thread thread = new Thread(new ThreadStart(LoadingHelper.ShowForm)); 27 thread.IsBackground = true; 28 thread.SetApartmentState(ApartmentState.STA); 29 thread.Start(); 30 31 } 32 33 /// <summary> 34 /// 显示窗口 35 /// </summary> 36 private static void ShowForm() 37 { 38 if (loadingForm != null) 39 { 40 loadingForm.closeOrder(); 41 loadingForm = null; 42 } 43 loadingForm = new LoaderForm(); 44 loadingForm.TopMost = true; 45 loadingForm.ShowDialog(); 46 } 47 48 /// <summary> 49 /// 关闭窗口 50 /// </summary> 51 public static void CloseForm() 52 { 53 Thread.Sleep(50); //可能到这里线程还未起来,所以进行延时,可以确保线程起来,彻底关闭窗口 54 if (loadingForm != null) 55 { 56 lock (syncLock) 57 { 58 Thread.Sleep(50); 59 if (loadingForm != null) 60 { 61 Thread.Sleep(50); //通过三次延时,确保可以彻底关闭窗口 62 loadingForm.Invoke(new CloseDelegate(LoadingHelper.CloseFormInternal)); 63 } 64 } 65 } 66 } 67 68 /// <summary> 69 /// 关闭窗口,委托中使用 70 /// </summary> 71 private static void CloseFormInternal() 72 { 73 74 loadingForm.closeOrder(); 75 loadingForm = null; 76 77 } 78 79 }
2.LoaderForm窗体具体代码如下。
1 public partial class LoaderForm : Form 2 { 3 4 public LoaderForm() 5 { 6 InitializeComponent(); 7 } 8 9 /// <summary> 10 /// 关闭命令 11 /// </summary> 12 public void closeOrder() 13 { 14 if (this.InvokeRequired) 15 { 16 //这里利用委托进行窗体的操作,避免跨线程调用时抛异常,后面给出具体定义 17 CONSTANTDEFINE.SetUISomeInfo UIinfo = new CONSTANTDEFINE.SetUISomeInfo(new Action(() => 18 { 19 while (!this.IsHandleCreated) 20 { 21 ; 22 } 23 if (this.IsDisposed) 24 return; 25 if (!this.IsDisposed) 26 { 27 this.Dispose(); 28 } 29 30 })); 31 this.Invoke(UIinfo); 32 } 33 else 34 { 35 if (this.IsDisposed) 36 return; 37 if (!this.IsDisposed) 38 { 39 this.Dispose(); 40 } 41 } 42 } 43 44 private void LoaderForm_FormClosing(object sender, FormClosingEventArgs e) 45 { 46 if (!this.IsDisposed) 47 { 48 this.Dispose(true); 49 } 50 51 } 52 53 }
对LoaderForm窗体相关说明:
1.public delegate void SetUISomeInfo(); //定义一个委托,处理UI相关信息问题。
2.LoaderForm窗体上放置了一个label,将其AutoSize属性设置为false,并将LoaderForm的TransparencyKey属性设置为Transparent(这样设置避免在加载loading框时出现背景,loading.gif最好选择透明背景的图片)。
至此,一个完整的loading框,已经搞定。
by Shawn Chen,2017.7.2日,晚。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)