C# 多线程窗体的创建
从目前已经在项目中工作将近一个月来的情况来看,凡是费时的操作,基本上都要用到多线程的等待窗体、进度提示窗体等实时显示动态的进度信息。而如果直接在主线程的窗体上实时更新信息,就会造成更新太快或者太慢而出现的进程假死现象。为了缓解这些情况,本文就参考一些文章,把他们的智慧总结于此。希望对大家有所帮助。
一、多线程中创建等待窗体
在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# 多线程窗体的创建的更多相关文章
- C# WinForm 单例模式(例:同一个窗体只创建一次实例)
//C# WinForm 单例模式(例:同一个窗体只创建一次实例) //打开窗体的事件: Form3 f = Form3.InstanceObject() ; //实例化窗体 f.Focus(); / ...
- delphi 窗体的创建和释放
Delphi中的窗体分为模式窗体和无模式窗体.二者的区别在于,用户可以在无模式窗体和其他窗体之间切换.这样,用户就可以同时工作于一个应用程序的几个部分.Delphi中窗体的初始化有两种情况,动态创建, ...
- Java多线程——线程的创建方式
Java多线程——线程的创建方式 摘要:本文主要学习了线程的创建方式,线程的常用属性和方法,以及线程的几个基本状态. 部分内容来自以下博客: https://www.cnblogs.com/dolph ...
- Java:多线程概述与创建方式
目录 Java:多线程概述与创建方式 进程和线程 并发与并行 多线程的优势 线程的创建和启动 继承Thread类 start()和run() 实现Runnable接口 实现Callable接口 创建方 ...
- Qt多线程学习:创建多线程
[为什么要用多线程?] 传统的图形用户界面应用程序都仅仅有一个运行线程,而且一次仅仅运行一个操作.假设用户从用户界面中调用一个比較耗时的操作,当该操作正在运行时,用户界面一般会冻结而不再响应.这个问题 ...
- Java多线程系列-线程创建
1.怎样创建多线程? Java从语言级别实现多线程,因此实现一个多线程程序很easy.有两种方法能够实现多线程,即继承Thread类和实现Runnable接口.由于Java不支持多继承的原因,建议尽可 ...
- Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)
线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...
- Delphi MDI 子窗体的创建和销毁 [zhuan]
1.如果要创建一个mdi child,先看是否有这个child 存在,如果有,则用它,如果没有再创建 //该函数判断MDI 子窗体是否存在,再进行创建和显示function isInclude(for ...
- Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)
线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...
随机推荐
- oracle之 12.1.0.1.0 C 在 linux 7 上安装报错处理
环境说明:-- os[root@host-172-16-3-132 ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) - ...
- CentOS6.5安装中文支持
本人在安装CentOS6.5时选择是英文版,安装后打开文档,发现好些文档成了乱码了. 这个问题的原因是没有中文支持. 解决方法: 1.安装中文支持包 # yum groupinstall " ...
- jdk1.8新特性之lambda表达式
lambda表达式其实就是指一个匿名函数,应用最广泛的就是匿名内部类的简化.在jdk1.8之前,我们定义一个匿名内部类可能需要写一大坨代码,现在有了lambda之后,可以写的很简洁了.但不是说lamb ...
- 【yii2从Apache迁移到nginx上访问报500错误】
[yii2从Apache迁移到nginx上访问报500错误] 今天迁移yii2项目从Apache到nginx,出现了几个小问题,记录一下 index.php 加上 error_reporting(E_ ...
- STL容器的resize方法
刚才写DFS程序,为了加个创建DFS树然后再次遍历的功能,把初始化的代码给封装到init()函数里,然后直接调用之后对同样是邻接表表示的DFS树进行DFS. 然后令人诧异的是竟然没有打印结果,调试发现 ...
- (转)Inno Setup入门(十三)——Pascal脚本(2)
本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17250933 事件函数(2) function CheckPassw ...
- (转)Inno Setup入门(二)——修改安装过程中的图片
本文转载自:http://blog.csdn.net/augusdi/article/details/8564793 修改安装过程中的图片 一般编译之后,安装过程中出现在左边图片是是下图这个样子的: ...
- Tomcat 8.5 架构分析
官方文档:Apache Tomcat 8 Architecture 以下分析的是 Version 8.5. Tomcat 组件关系图 根据 Architecture Overview 绘制: Serv ...
- JAVA代码实现从文件写入东西后有读出来=========FileInputStream
总结: 这个原理是,先把for循环里的数从程序读到文件里,然后把文件把内容读到程序里 package com.a.b; import java.io.FileInputStream; import j ...
- GTID 跳过脚本
跳过单个error STOP SLAVE; SET gtid_next = '3b977b7e-ed28-11e7-a8ff-b4969113b678:138609841'; BEGIN;COMMIT ...