一、知识点介绍
1,更新控件的内容,应该调用控件的Invoke方法。
Invoke指: 在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。该方法接收一个委托类型和委托的参数,因此需要定义委托类型变量,然后传递给Invoke方法。
 
如果其他线程直接调用方法更新控件内容,报错:线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。
 
2,委托的本质是某一类型的方法,这些方法具有相同的参数和返回类型。
委托类似于C语言中的函数指针,可以指向多个相同类型的函数。
定义委托,只需要在函数返回类型前加上delegate关键词,把函数体大括号{}的内容换成分号即可。比如:
public delegate void DelegateFun(string msg);
DelegateFun就代表了一个函数类型,它接收string参数,返回void。
 
3,开辟一个线程,直接启动,后面通过挂起和唤醒实现暂停功能。
Thread t = new Thread(Run);
t.Start(); // 启动
通过判断线程状态,决定是否唤醒线程。
if (t.ThreadState == ThreadState.Suspended) // 如果被挂起了,就唤醒
{
t.Resume();
}
暂停就挂起线程:
t.Suspend(); // 停止,挂起线程
 
注:也可以定义一个开关,用来控制开始和结束,在开关为false的时候,直接continue,这样表现为暂停输出,但是实际上线程一直在运行。
 
二、界面和代码
 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading; namespace WindowsFormsApplication3
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
} /// <summary>
/// 因为控件的Invoke方法需要接收委托变量,因此需要定义委托和委托变量
/// 定义一个委托,接收一个参数
/// </summary>
/// <param name="msg"></param>
public delegate void DelegateFun(string msg);
/// <summary>
/// 定义一个委托变量
/// 这个委托变量,需要初始化指定具体的方法;然后传递给控件的Invoke方法调用。
/// </summary>
public DelegateFun Fun1; /// <summary>
/// 定义一个线程,处理数据,并更新界面
/// </summary>
private Thread t = null;
// 开始按钮
private void button1_Click(object sender, EventArgs e)
{
this.Invoke(Fun1, "开始..."); // 增加判断,避免每次单击都开辟一个线程
if (t == null)
{
t = new Thread(Run);
t.Start();
}
if (t.ThreadState == ThreadState.Suspended) // 如果被挂起了,就唤醒
{
t.Resume();
} }
// 结束执行
private void button2_Click(object sender, EventArgs e)
{
t.Suspend(); // 停止,挂起线程
this.Invoke(Fun1, "...停止");
} // 具体做事情的方法
public void Run()
{
//...... 处理一些事情,然后输出日志
int i = ;
while (true)
{
i++;
// this指Form2
//Invoke指: 在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。
//Invoke的参数是一个委托类型,因此必须定义委托变量
this.Invoke(Fun1, i.ToString());
}
} //在form初始化的时候,给委托变量赋值具体的方法
private void Form2_Load(object sender, EventArgs e)
{
//给委托变量初始化具体的执行方法
Fun1 = Print;
} // 输出日志的方法
public void Print(string msg)
{
// 新开辟的线程,不能直接调用这个方法。原因是控件只能由创建它的线程调用。
// 其他线程调用提示错误: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。
this.richTextBox1.AppendText(msg + "\r\n");
this.richTextBox1.ScrollToCaret();
} }
}
 

 
三、参考文章
1, C#多线程解决界面卡死问题的完美解决方案,BeginInvoke而不是委托delegate

多线程、委托、Invoke解决winform界面卡死的问题,并带开关的更多相关文章

  1. 双缓冲队列解决WPF界面卡死

    工作中的项目,CS客户端会通过MQ接收前端设备发送的信息,之前测试的时候,由于测试的数据不大,没有进行压力测试,软件可以正常工作,随着项目现场设备数量的增加,CS客户端从MQ中订阅的数据量不断增加,最 ...

  2. 使用multiprocessing解决PyMuPDF不支持多线程加载导致的界面卡死无响应问题,及一个PyQt5实现的简易PDF阅读器例子

    最近在用PyMuPDF实现一个PDF阅读器,发现PyMuPDF在加载某些epub时耗时非常长,有的长达10几秒,会导致界面卡死无响应. 尝试用多线程后台加载,发现还是不能解决问题,和作者交流(issu ...

  3. Centos7解决图形界面卡死问题

    经常会遇到图形界面卡死,搜了一搜,解决办法如下: killall -9 gnome-shell

  4. 【C#】多线程解决UI界面卡死的问题

    一个经典的例子: http://www.cnblogs.com/wangchuang/p/4485797.html 问题: 都说Invoke是同步的,BeginInvoke是异步的,但为何用Begin ...

  5. 解决 winform 界面对不齐 z

    一个winform的程序,本机上界面对得很齐,到一到客户的机器上就惨不忍睹,一番研究后搞定: 1. AutoScaleMode = None 2. BackgroundImageLayout = No ...

  6. 解决 winform 界面对不齐

    最近做了一个winform的程序,本机上界面对得很齐,到一到客户的机器上就惨不忍睹,一番研究后搞定: 1. AutoScaleMode = None 2. BackgroundImageLayout ...

  7. 解决WinForm界面闪烁问题

    前言 之前將.net 1.1 Windows Form程式升級到.net 4.0,結果在開畫面時,閃的非常利害!  於是就開始找解決方法. 研究及解決 開始找到了設定DoubleBuffer=true ...

  8. C#多线程解决界面卡死问题的完美解决方案,BeginInvoke而不是委托delegate 转载

    问题描述:当我们的界面需要在程序运行中不断更新数据时,当一个textbox的数据需要变化时,为了让程序执行中不出现界面卡死的现像,最好的方法就是多线程来解决一个主线程来创建界面,使用一个子线程来执行程 ...

  9. WinForm多线程+委托防止界面卡死

    1.当有大量数据需要计算.显示在界面或者调用sleep函数时,容易导致界面卡死,可以采用多线程加委托的方法解决 using System; using System.Collections.Gener ...

随机推荐

  1. ubuntu 好玩多了

    从一开始的咒骂,到慢慢的喜欢,ubuntu比CentOs可玩多了.

  2. js词法分析

    JavaScript的高级知识---词法分析 词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 函数在运行的瞬间, ...

  3. [MySQL]show index from tb_name命令各列的含义

    show index from table_name 这个命令有助于诊断性能低下的查询,尤其是查询是否使用了可用的索引. 下面介绍下 这个命令显示的结果列的含义: | Table | Non_uniq ...

  4. go:关于变量地址的疑惑

    定义一些变量,并输出其地址 一.一般变量 var a, b int32 var c, d int64 输出其地址 结果: a 0xc082006310 b 0xc082006320 c 0xc0820 ...

  5. spring framework核心框架体系结构

    很实用,稀里糊涂的我算是看清了. 很多人都在用spring开发java项目,但是配置maven依赖的时候并不能明确要配置哪些spring的jar,经常是胡乱添加一堆,编译或运行报错就继续配置jar依赖 ...

  6. select样式美化(简单实用)

    美化select,可以实用一个a标签将select嵌套进去,然后将<a>相对定位,在将select绝对定位,美化<a>即可 文件下载链接:https://i.cnblogs.c ...

  7. 安装yum

    RedHat 安装配置 YUM 删除 1 . 查询系统是否安装 yum : rpm – qa|grep yum 2删除原有 yum rpm -qa|grep yum|xargs rpm -e – no ...

  8. squid 2.7 通过域名反向代理多个服务器的配置方法

    详细配置及注释如下,供大家学习参考. visible_hostname squid1.abc.com #设定squid的主机名,如无此项squid将无法启动 http_port 80 accel vh ...

  9. tp框架之函数调用

    1.如果要在一个方法里面调用另一个方法,可以先用A方法实例化控制器 $m = A("控制器名"); ,然后根据方法名调用 $m->方法名(可传参数); 2.自定义函数库  ( ...

  10. 配置比对脚本(python)

    # -*- coding: utf- -*- from datetime import * import MySQLdb import sys import time import datetime ...