从目前已经在项目中工作将近一个月来的情况来看,凡是费时的操作,基本上都要用到多线程的等待窗体、进度提示窗体等实时显示动态的进度信息。而如果直接在主线程的窗体上实时更新信息,就会造成更新太快或者太慢而出现的进程假死现象。为了缓解这些情况,本文就参考一些文章,把他们的智慧总结于此。希望对大家有所帮助。

一、多线程中创建等待窗体

  在winform程序开发中,计算机经常会执行一些比较耗时的任务,如大量数据的查询操作、较为复杂的业务处理等,这些任务往往需要耗时几秒到几十秒钟的时间,在这些任务执行期间winform程序窗体不再响应任何鼠标和键盘事件,出现假死状态,用户体验很差。

  一个比较好的解决办法是,在这些任务执行期间在界面前端显示一个等待窗体,告诉用户任务正在执行中。

1.1 开发等待窗体

窗体中有一个PictureBox控件和两个Lable控件,PictureBox控件的Image属性为一张动态图片。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using NavManager.Common; namespace NavManager.Utils
{
public partial class WaitForm : Form
{
public WaitForm()
{
InitializeComponent();
SetText("");
} private delegate void SetTextHandler(string text);
public void SetText(string text)
{
if (this.label2.InvokeRequired)
{
this.Invoke(new SetTextHandler(SetText), text);
}
else
{
this.label2.Text = text;
}
}
}
}

等待窗体源码

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)
{
}
}
} }
}

WaitFormService Class Code

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();
}

接口的使用

参考文章

1. 飘落纸飞机C# winform 多线程中创建等待窗体,2011。

C# 多线程窗体的创建的更多相关文章

  1. C# WinForm 单例模式(例:同一个窗体只创建一次实例)

    //C# WinForm 单例模式(例:同一个窗体只创建一次实例) //打开窗体的事件: Form3 f = Form3.InstanceObject() ; //实例化窗体 f.Focus(); / ...

  2. delphi 窗体的创建和释放

    Delphi中的窗体分为模式窗体和无模式窗体.二者的区别在于,用户可以在无模式窗体和其他窗体之间切换.这样,用户就可以同时工作于一个应用程序的几个部分.Delphi中窗体的初始化有两种情况,动态创建, ...

  3. Java多线程——线程的创建方式

    Java多线程——线程的创建方式 摘要:本文主要学习了线程的创建方式,线程的常用属性和方法,以及线程的几个基本状态. 部分内容来自以下博客: https://www.cnblogs.com/dolph ...

  4. Java:多线程概述与创建方式

    目录 Java:多线程概述与创建方式 进程和线程 并发与并行 多线程的优势 线程的创建和启动 继承Thread类 start()和run() 实现Runnable接口 实现Callable接口 创建方 ...

  5. Qt多线程学习:创建多线程

    [为什么要用多线程?] 传统的图形用户界面应用程序都仅仅有一个运行线程,而且一次仅仅运行一个操作.假设用户从用户界面中调用一个比較耗时的操作,当该操作正在运行时,用户界面一般会冻结而不再响应.这个问题 ...

  6. Java多线程系列-线程创建

    1.怎样创建多线程? Java从语言级别实现多线程,因此实现一个多线程程序很easy.有两种方法能够实现多线程,即继承Thread类和实现Runnable接口.由于Java不支持多继承的原因,建议尽可 ...

  7. Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  8. Delphi MDI 子窗体的创建和销毁 [zhuan]

    1.如果要创建一个mdi child,先看是否有这个child 存在,如果有,则用它,如果没有再创建 //该函数判断MDI 子窗体是否存在,再进行创建和显示function isInclude(for ...

  9. Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

随机推荐

  1. swift 数组作为函数参数的书写格式

    数组定义 --[来自百度知道] Swift语言使用类型名紧接中括号[]来简化标准库中定义的命名型类型Array.例如 Array<String> = ["Alex", ...

  2. Linux操作系统设置SSH及SFTP通过密钥登录

    如果你使用过Linux操作系统的VPS或其他服务器,可能在登录时经常会提示你有多少次登录失败的记录. 这种登录失败的记录实际上也就是攻击者使用脚本自动扫描全网的IP然后进行筛选和测试,最终脚本会使用内 ...

  3. Luogu 1452 Beauty Contest

    Luogu 1452 Beauty Contest 求平面最远点对,先求出凸包,再找凸包的直径. 使用旋转卡壳,直径一定出现在对踵点对间.比较不同点到同一直线距离可以用叉积算三角形面积来比较. 实现时 ...

  4. LOJ2422 NOIP2015 斗地主 【搜索+贪心】*

    LOJ2422 NOIP2015 斗地主 LINK 题目大意很简单,就是问你斗地主的一分手牌最少多少次出完 然后我们发现对于一种手牌状态,不考虑顺子的情况是可以贪心做掉的 然后我们直接枚举一下顺子出牌 ...

  5. BZOJ4518 Sdoi2016 征途 【斜率优化DP】 *

    BZOJ4518 Sdoi2016 征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m ...

  6. jdbcTemplate的一些常用方法

    前言 最近的项目中由于只进行查询,所以使用了jdbcTemplate来直接操作sql进行持久层的操作,初次接触jdbcTemplate,从最开始的什么都不知道到现在基本方法都大致知道什么意思,特此记录 ...

  7. 浅谈ES6新特性

    ES6的了解 新增模板字符串(为JavaScript提供了简单的字符串插值功能).箭头函数(操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs.).for-o ...

  8. hoverfly api 模拟框架了解

    What is Hoverfly? Hoverfly is a lightweight, open source API simulation tool. Using Hoverfly, you ca ...

  9. Clair:CoreOS发布的开源容器漏洞分析工具

    Clair为何而生:提升安全 软件世界里,安全漏洞会一直存在.好的安全实践意味着要对可能出现的事故未雨绸缪 - 即尽早发现不安全的软件包,并准备好快速进行升级.而Clair就是设计来帮助你找出容器中可 ...

  10. Linux 制作补丁 打补丁 撤销补丁

    1.制作补丁 diff - 逐行比较文件 格式 diff   参数   旧文件/旧文件夹   新文件/新文件夹 -N   将不存在的文件看作是空的 -a   将所有文件都视为文本文件 -u   以合并 ...