使用线程新建WPF窗体(公用进度条窗体)
时间:2022-05-03
本文章向大家介绍使用线程新建WPF窗体(公用进度条窗体),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
使用线程新建窗体
项目中需要一个公用的进度条窗体.大家知道在wpf中,有两个线程,一个是UI线程,另一个是监听线程(一直监听用户的输入).如果我们后台有阻塞UI线程的计算存在,那么界面上的比如进度条什么动态的UI都会被因为阻塞而静止不动.
所以我的想法就是新起一个线程来负责进度条窗体的显示与关闭,具体实现代码如下:
private static Thread th;
/// <summary>
/// 显示进度条 线程
/// </summary>
/// <param name="msg">进度条界面需要显示的文字</param>
/// <param name="sleep">增加进度条存在的延迟时间,单位为毫秒</param>
public static void BeginProgressBar(string msg, int sleep)
{
try
{
if (th == null || th.ThreadState == ThreadState.Aborted)
{
th = new Thread(new ThreadStart(() =>
{
WinProgressBar win = new WinProgressBar();
win.Tips = msg;
win.Topmost = true;
win.Show();
System.Windows.Threading.Dispatcher.Run();
}));
th.SetApartmentState(ApartmentState.STA);
th.IsBackground = true;
}
if (th.ThreadState != ThreadState.Background || th.ThreadState == ThreadState.Unstarted || th.ThreadState != ThreadState.Running)
{
th.Start();
}
}
catch (Exception)
{
th = new Thread(new ThreadStart(() =>
{
WinProgressBar win = new WinProgressBar();
win.Tips = msg;
win.Topmost = true;
win.Show();
System.Windows.Threading.Dispatcher.Run();
}));
th.SetApartmentState(ApartmentState.STA);
th.IsBackground = true;
th.Start();
}
Thread.Sleep(sleep);
}
/// <summary>
/// 结束进度条
/// </summary>
public static void EndProgressBar()
{
if (th.IsAlive)
th.Abort();
}
呵呵,大家仔细分析下代码看有什么问题没有?而你们又有什么好的解决方案没有?
在使用过程中发现一个很严重的问题,出现一个进度条窗体,系统内存就会增大一点,到最后要么卡死,要么自动退出.
原来在多线程程序运行中,由用户取消操作是一种非常常见的场景,比如用户使用windows资源管理器在当前文件夹中搜索文件时,可以通过点击其它文件夹而取消搜索。 中途停止一个线程的执行,通常用Thread.Abort方法,但这种方式会造成程序涉及的数据完整性受到破坏,线程所占用的一些系统资源(比如文件句柄等)也可能无法完成。比较合理的方式是外界提出"取消操作"的请求,然后由线程自身来决定如何处理这一请求。 在设计多线程程序时,可设置一个用于接收外部取消消息的属性,然后在线程函数中分阶段地检测这一属性,每个阶段的检查点由软件开发者确定,并且决定线程如何优雅退出。
所以对上述代码进行了改进
首先设置一个公共变量:
public static bool IsClsoeProgeressBar = true;
然后在进度条窗体中实时读这个数据
/// <summary>
/// WinProgressBar.xaml 的交互逻辑
/// </summary>
public partial class WinProgressBar : Window
{
public string Tips { get; set; }
DispatcherTimer timer;
public WinProgressBar()
{
InitializeComponent();
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(200);
timer.Tick += new EventHandler(timer_Tick);
timer.IsEnabled = true;
this.Topmost = true;
//this.Loaded += delegate
//{
// if (this.Tips != "")
// tbTips.Text = this.Tips;
//};
}
void timer_Tick(object sender, EventArgs e)
{
if (Common.CommWindow.IsClsoeProgeressBar)
{
if (this.Visibility == Visibility.Visible)
{
progressBar1.IsIndeterminate = false;
this.Hide();
}
}
else
{
if (this.Visibility != Visibility.Visible)
{
progressBar1.IsIndeterminate = true;
this.Show();
}
}
}
}
然后在系统加载的时候,创建这个进度条窗体
try
{
Thread th = new Thread(new ThreadStart(() =>
{
WinProgressBar win = new WinProgressBar();
// win.Tips = msg;
win.Show();
System.Windows.Threading.Dispatcher.Run();
}));
th.SetApartmentState(ApartmentState.STA);
th.IsBackground = true;
th.Start();
}
catch (Exception)
{
}
我们只需改变公共变量来控制窗体的显示与隐藏
/// <summary>
/// 显示进度条 线程
/// </summary>
public static void BeginProgressBar()
{
IsClsoeProgeressBar = false;
}
/// <summary>
/// 结束进度条
/// </summary>
public static void EndProgressBar()
{
//cts.Cancel();
IsClsoeProgeressBar = true;
}
还有一个比较好的方法:
#region Methods
/// <summary>
/// 一个耗时的任务
/// </summary>
private void BigTask()
{
Thread.Sleep(3000);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MyProgressBar(BigTask);
}
private void MyProgressBar(Action mywork)
{
var worker = new BackgroundWorker();
var window = new BusyWindow();
worker.DoWork += (s, e2) => { mywork(); };
worker.RunWorkerCompleted += (s, e2) =>
{
MessageBox.Show("任务已经完成");
window.Close();
};
worker.RunWorkerAsync();
window.Show();
}
#endregion
这个由网友热情的沙漠提供,也很不错,大家可以参考下
- Asp.net页面生命周期
- Premiere&After Effects的实时预览插件开发
- 委托与事件
- 一款批量修改AE模板的工具
- 深入线程
- 【插件开发】—— 2 插件入门
- 线程间通讯:WaitHandler使用实例及分析
- 域名Deskbike.com刚注册没多久就以五位数结拍
- 一起Polyfill系列:Function.prototype.bind的四个阶段
- winform实现拼图游戏
- 一起Polyfill系列:让Date识别ISO 8601日期时间格式
- Oracle 监听器无法启动(TNS-12537,TNS-12560,TNS-00507)
- Javascript Prototypes之旅(A Plain English Guide to JavaScript Prototypes译文)
- Python补充03 Python内置函数清单
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 七大设计原则、单一职责原则
- JSP 基本凉凉,学妹不知道他是啥
- Codeforces Round #615 (Div. 3)C. Product of Three Numbers
- Codeforces Round #622 (Div. 2) A.Fast Food Restaurant
- 渗透测试实战 | 一次信息泄露引发的越权
- Vue创建项目及基本语法 一
- 学 Java 开发怎么能不知道 Filter 与 Listener
- Windows 安装 MySQL 常见问题
- LootCode-链表排序-Java
- 好久不用 jQuery, 来复习一下
- Spring学习一、组件注册
- 复习 EL 表达式与 JSTL
- Spring 学习二、Bean生命周期相关注解
- 十分钟学会 HTML
- 聊一下会话跟踪技术