从目前已经在项目中工作将近一个月来的情况来看,凡是费时的操作,基本上都要用到多线程的等待窗体、进度提示窗体等实时显示动态的进度信息。而如果直接在主线程的窗体上实时更新信息,就会造成更新太快或者太慢而出现的进程假死现象。为了缓解这些情况,本文就参考一些文章,把他们的智慧总结于此。希望对大家有所帮助。
一、多线程中创建等待窗体
在winform程序开发中,计算机经常会执行一些比较耗时的任务,如大量数据的查询操作、较为复杂的业务处理等,这些任务往往需要耗时几秒到几十秒钟的时间,在这些任务执行期间winform程序窗体不再响应任何鼠标和键盘事件,出现假死状态,用户体验很差。
一个比较好的解决办法是,在这些任务执行期间在界面前端显示一个等待窗体,告诉用户任务正在执行中。
1.1 开发等待窗体
![]()
窗体中有一个PictureBox控件和两个Lable控件,PictureBox控件的Image属性为一张动态图片。
等待窗体源码
1.2 提供访问等待窗体的接口
编写类WaitFormService
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace NavManager.Utils
{
/// <summary>
/// Using Singleton Design Pattern
/// </summary>
public class WaitFormService
{
public static void CreateWaitForm()
{
WaitFormService.Instance.CreateForm();
}
public static void CloseWaitForm()
{
WaitFormService.Instance.CloseForm();
}
public static void SetWaitFormCaption(string text)
{
WaitFormService.Instance.SetFormCaption(text);
}
private static WaitFormService _instance;
private static readonly Object syncLock = new Object();
public static WaitFormService Instance
{
get
{
if (WaitFormService._instance == null)
{
lock (syncLock)
{
if (WaitFormService._instance == null)
{
WaitFormService._instance = new WaitFormService();
}
}
}
return WaitFormService._instance;
}
}
private WaitFormService()
{
}
private Thread waitThread;
private WaitForm waitForm;
public void CreateForm()
{
if (waitThread != null)
{
try
{
waitThread.Abort();
}
catch (Exception)
{
}
}
waitThread = new Thread(new ThreadStart(delegate()
{
waitForm = new WaitForm();
Application.Run(waitForm);
}));
waitThread.Start();
}
public void CloseForm()
{
if (waitThread != null)
{
try
{
waitThread.Abort();
}
catch (Exception)
{
}
}
}
public void SetFormCaption(string text)
{
if (waitForm != null)
{
try
{
waitForm.SetText(text);
}
catch (Exception)
{
}
}
}
}
}
1.3 使用WaitFormService提供的接口
try
{
WaitFormService.CreateWaitForm();
Assembly asmb = Assembly.GetExecutingAssembly();
Object obj = asmb.CreateInstance(className);
Form frm = obj as Form;
this.ShowMenu(frm);
WaitFormService.CloseWaitForm();
}
catch (Exception ex)
{
WaitFormService.CloseWaitForm();
}
补充:
还有一个类似网页:C# 使用委托实现多线程调用窗体的四种方式