使用publisher模式控制频繁的UI输出,避免Winform界面假死
http://www.cnblogs.com/Charltsing/p/publisher.html
最近测试task并发任务的效率与线程池的区别,发现了另外一个问题。task建立任务的速度很快,输出到UI的信息过频,导致UI假死。
private void TestMakeTasks(object obj)
{
string msg = ""; //循环创建task
for (int i = 0; i < 3000; i++)
{
//主线程(winform)--子线程(Thread)--工作线程(task)
//不能在循环里面连续访问UI,会造成UI来不及处理,导致假死。
Task<string> tt = Task.Factory.StartNew<string>(test, i);
tt.ContinueWith((t) =>
{
if (t.IsFaulted)
{
string msgexcep = (string.Format("I have observed a {0}", t.Exception.InnerException.GetType().Name));
Interlocked.Increment(ref responsecount);
Interlocked.Decrement(ref threadscount);
}
});
//Thread.Sleep(1); //避免过快发送UI更新请求,导致假死。
msg = " 已发送请求数:" + requestcount.ToString() + " 已完成请求数:" + responsecount.ToString(); //输出线程建立信息给UI,过频会导致假死。
PublishStatus(msg); Interlocked.Increment(ref threadscount);
Interlocked.Increment(ref requestcount);
if (_isStop)
{
PublishMessage("正在退出...\r\n");
break;
}
}
PublishMessage("发送完毕,请等待线程运行完毕!\r\n");
while (responsecount < requestcount)
{
Thread.Sleep(300);
msg = "!已发送请求数:" + requestcount.ToString() + " 已完成请求数:" + responsecount.ToString();
PublishStatus(msg);
}
_isRunning = false;
PublishMessage("\r\n全部线程运行完毕!\r\n");
}
为了解决这个问题,考虑使用publisher模式控制UI输出
public class Publisher
{
public bool isbusy = false; //标志
public delegate void PublishEventHander(object sender, PubEventArgs e); public event PublishEventHander PublishMessage;
public event PublishEventHander PublishStatus; //声明一个可重写的OnPublish的保护函数
protected virtual void OnPublishMessage(PubEventArgs e)
{
if (PublishMessage != null)
{
//Sender = this,也就是Publisher
this.PublishMessage(this, e);
}
}
protected virtual void OnPublishStatus(PubEventArgs e)
{
if (PublishStatus != null)
{
//Sender = this,也就是Publisher
this.PublishStatus(this, e);
}
} /// <summary>
/// 触发publish message事件
/// </summary>
public void IssueMessage(string message)
{
OnPublishMessage(new PubEventArgs(message));
} /// <summary>
/// 触发publish status事件
/// </summary>
public void IssueStatus(string message)
{
if (!isbusy) OnPublishStatus(new PubEventArgs(message)); }
}
同时,在UI输出部分,使用Invoke来阻止更多的UI操作(不能使用BeginInvoke)。
private void WriteStatus(string msg)
{
if (this.lblStatus.InvokeRequired)
{
Invoke(cdWriteStatus, msg);
}
else
{
UpdatelblMethod(msg);
}
}
大致思路是 task创立任务之后,发给publisher一个通知(使用IssueStatus函数),publisher通过OnPublishStatus事件通知给Subscriber,UI界面作为订阅者通过设置publisher的busy状态使得publisher取消后面多余的输出事件。
有问题请联系QQ 564955427
使用publisher模式控制频繁的UI输出,避免Winform界面假死的更多相关文章
- Qt多线程和GUI界面假死(run()是线程的入口,就像main()对于应用程序的作用。分析QThread::exec函数的源码,旧的QMutexLocker模式其实很好用,挡住别人进入抢占资源,可照抄)good
QThread的常见特性: run()是线程的入口,就像main()对于应用程序的作用.QThread中对run()的默认实现调用了exec(),从而创建一个QEventLoop对象,由其处理该线程事 ...
- TIMER门控模式控制PWM输出长度
TIMER门控模式控制PWM输出长度 参照一些网友代码做了些修改,由TIM4来控制TIM2的PWM输出长度, 采用主从的门控模式,即TIM4输出高时候TIM2使能输出 //TIM2 PWM输出,由TI ...
- STM32: TIMER门控模式控制PWM输出长度
搞了两天单脉冲没搞定,无意中发现,这个利用主从模式的门控方式来控制一路PWM的输出长度很有效. //TIM2 PWM输出,由TIM4来控制其输出与停止 //frequency_tim2:TIM2 PW ...
- AMQ学习笔记 - 19. 问题解决 - 控制Atomikos的日志输出
概述 在使用Atomikos为ActiveMQ提供JTA支持时,Atomikos在控制台打印了繁琐的日志.这里介绍如何控制Atomikos日志输出的粒度. 解决方案 基于以下三个事实: Atomiko ...
- Client-Side UI Automation Provider - WinForm Sample
Client-Side UI Automation Provider - WinForm Sample 2014-09-15 源代码 目录 引用程序集实现提供程序接口分发客户端提供程序注册和配置客户 ...
- Server-Side UI Automation Provider - WinForm Sample
Server-Side UI Automation Provider - WinForm Sample 2014-09-14 源代码 目录 引用程序集提供程序接口公开服务器端 UI 自动化提供程序从 ...
- 告诉你吧,一套皮肤在winform与wpf开发模式下实现的界面效果同样精彩,winform界面和wpf界面。
一.同一资源: 二.先上软件界面: (1)wpf界面: 在wpf中实现这样类似web风格的软件界面就不用我多说了,在wpf实现这样的风格是很简单的,完全像网页设计一样的. (2)winform界面 在 ...
- C#:控制WinForm界面的显示
控制WinForm界面在屏幕的四个角落显示,具体代码中有说明: using System; using System.Collections.Generic; using System.Drawing ...
- Winform 界面执行耗时操作--UI卡顿假死问题
UI卡顿假死问题 误区1:使用不同的线程操作UI控件和耗时操作(即,跨线程操作UI控件CheckForIllegalCrossThreadCalls = false;), 注意:此处只是为了记录... ...
随机推荐
- SMB协议利用之ms17-010-永恒之蓝漏洞抓包分析SMB协议
SMB协议利用之ms17-010-永恒之蓝漏洞抓包分析SMB协议 实验环境: Kali msf以及wireshark Win7开启网络共享(SMB协议) 实验步骤: 1.查看本机数据库是否开启,发现数 ...
- SSH 和 Git
了解SSH SSH 以非对称加密实现身份验证.较常用的非对称加密有 RSA. 两种加密过程: 1.通过用户名密码访问服务器,即使传输的数据是加密的也可能会被劫持到不信任的服务器,泄露用户名和密码. 2 ...
- LeetCode算法题-Arranging Coins(Java实现)
这是悦乐书的第229次更新,第241篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第96题(顺位题号是441).您想要以楼梯形状形成总共n个硬币,其中每个第k行必须具有恰 ...
- February 21st, 2018 Week 8th Wednesday
Our life is what our thoughts make it. 我们的思想成就了我们的生活. The mind is everything. What you think, you be ...
- MySQL知识总结(一)安装与配置(Linux CentOS)
1 安装 环境 CentOS yum install -y mysql-server mysql mysql-deve service启动 1.1 启动 service mysqld start 1. ...
- node.js—Buffer类(二进制数据处理模块)
Buffer类概述 一个用于更好的操作二进制数据的类 我们在操作文件或者网络数据的时候,其实操作的就是二进制数据流 Node为我们提供了一个更加方便的去操作这种数据流的类 Buffer,他是一个全局的 ...
- 16.ajax_case04
# 抓取金色财经快讯接口 # https://www.jinse.com/lives import requests import json header = { 'Accept': 'text/ht ...
- 机器学习算法总结(五)——聚类算法(K-means,密度聚类,层次聚类)
本文介绍无监督学习算法,无监督学习是在样本的标签未知的情况下,根据样本的内在规律对样本进行分类,常见的无监督学习就是聚类算法. 在监督学习中我们常根据模型的误差来衡量模型的好坏,通过优化损失函数来改善 ...
- Quartz动态添加定时任务执行sql(服务启动添加+手动添加)
系统用来每天插入视图数据... 一.数据库表设计 1.接口配置表(t_m_db_interface_config) 2.接口日志表(t_m_db_interface_log) 3.前端配置页面 查询页 ...
- Python 的全局变量
结论: Python 的全局变量只在本文件中生效. 定义全局变量的文件 G.py # define some global variable A = 1 B = 2 C = 3 def fuck(a= ...