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界面假死的更多相关文章

  1. Qt多线程和GUI界面假死(run()是线程的入口,就像main()对于应用程序的作用。分析QThread::exec函数的源码,旧的QMutexLocker模式其实很好用,挡住别人进入抢占资源,可照抄)good

    QThread的常见特性: run()是线程的入口,就像main()对于应用程序的作用.QThread中对run()的默认实现调用了exec(),从而创建一个QEventLoop对象,由其处理该线程事 ...

  2. TIMER门控模式控制PWM输出长度

    TIMER门控模式控制PWM输出长度 参照一些网友代码做了些修改,由TIM4来控制TIM2的PWM输出长度, 采用主从的门控模式,即TIM4输出高时候TIM2使能输出 //TIM2 PWM输出,由TI ...

  3. STM32: TIMER门控模式控制PWM输出长度

    搞了两天单脉冲没搞定,无意中发现,这个利用主从模式的门控方式来控制一路PWM的输出长度很有效. //TIM2 PWM输出,由TIM4来控制其输出与停止 //frequency_tim2:TIM2 PW ...

  4. AMQ学习笔记 - 19. 问题解决 - 控制Atomikos的日志输出

    概述 在使用Atomikos为ActiveMQ提供JTA支持时,Atomikos在控制台打印了繁琐的日志.这里介绍如何控制Atomikos日志输出的粒度. 解决方案 基于以下三个事实: Atomiko ...

  5. Client-Side UI Automation Provider - WinForm Sample

    Client-Side UI Automation Provider -  WinForm Sample 2014-09-15 源代码 目录 引用程序集实现提供程序接口分发客户端提供程序注册和配置客户 ...

  6. Server-Side UI Automation Provider - WinForm Sample

    Server-Side UI Automation Provider - WinForm Sample 2014-09-14 源代码  目录 引用程序集提供程序接口公开服务器端 UI 自动化提供程序从 ...

  7. 告诉你吧,一套皮肤在winform与wpf开发模式下实现的界面效果同样精彩,winform界面和wpf界面。

    一.同一资源: 二.先上软件界面: (1)wpf界面: 在wpf中实现这样类似web风格的软件界面就不用我多说了,在wpf实现这样的风格是很简单的,完全像网页设计一样的. (2)winform界面 在 ...

  8. C#:控制WinForm界面的显示

    控制WinForm界面在屏幕的四个角落显示,具体代码中有说明: using System; using System.Collections.Generic; using System.Drawing ...

  9. Winform 界面执行耗时操作--UI卡顿假死问题

    UI卡顿假死问题 误区1:使用不同的线程操作UI控件和耗时操作(即,跨线程操作UI控件CheckForIllegalCrossThreadCalls = false;), 注意:此处只是为了记录... ...

随机推荐

  1. SMB协议利用之ms17-010-永恒之蓝漏洞抓包分析SMB协议

    SMB协议利用之ms17-010-永恒之蓝漏洞抓包分析SMB协议 实验环境: Kali msf以及wireshark Win7开启网络共享(SMB协议) 实验步骤: 1.查看本机数据库是否开启,发现数 ...

  2. SSH 和 Git

    了解SSH SSH 以非对称加密实现身份验证.较常用的非对称加密有 RSA. 两种加密过程: 1.通过用户名密码访问服务器,即使传输的数据是加密的也可能会被劫持到不信任的服务器,泄露用户名和密码. 2 ...

  3. LeetCode算法题-Arranging Coins(Java实现)

    这是悦乐书的第229次更新,第241篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第96题(顺位题号是441).您想要以楼梯形状形成总共n个硬币,其中每个第k行必须具有恰 ...

  4. February 21st, 2018 Week 8th Wednesday

    Our life is what our thoughts make it. 我们的思想成就了我们的生活. The mind is everything. What you think, you be ...

  5. MySQL知识总结(一)安装与配置(Linux CentOS)

    1 安装 环境 CentOS yum install -y mysql-server mysql mysql-deve service启动 1.1 启动 service mysqld start 1. ...

  6. node.js—Buffer类(二进制数据处理模块)

    Buffer类概述 一个用于更好的操作二进制数据的类 我们在操作文件或者网络数据的时候,其实操作的就是二进制数据流 Node为我们提供了一个更加方便的去操作这种数据流的类 Buffer,他是一个全局的 ...

  7. 16.ajax_case04

    # 抓取金色财经快讯接口 # https://www.jinse.com/lives import requests import json header = { 'Accept': 'text/ht ...

  8. 机器学习算法总结(五)——聚类算法(K-means,密度聚类,层次聚类)

    本文介绍无监督学习算法,无监督学习是在样本的标签未知的情况下,根据样本的内在规律对样本进行分类,常见的无监督学习就是聚类算法. 在监督学习中我们常根据模型的误差来衡量模型的好坏,通过优化损失函数来改善 ...

  9. Quartz动态添加定时任务执行sql(服务启动添加+手动添加)

    系统用来每天插入视图数据... 一.数据库表设计 1.接口配置表(t_m_db_interface_config) 2.接口日志表(t_m_db_interface_log) 3.前端配置页面 查询页 ...

  10. Python 的全局变量

    结论: Python 的全局变量只在本文件中生效. 定义全局变量的文件 G.py # define some global variable A = 1 B = 2 C = 3 def fuck(a= ...