C#新开一个线程取到数据,如何更新到主线程UI上面
一:问题
之前有被面试官问过,在WinForm中,要去网络上获取数据,由于网络环境等原因,不能很快的完成,因此会发生进程阻塞,造成主进程假死的现象,需要怎么解决?
二:思路
因此,往往是新建一个线程,让他执行耗时的操作,主线程管理用户界面,不会出现UI假死的情况,但是通过线程获取到的数据如何更新回主进程的UI上呢?这是另外一个问题
三:如下例子
我们发现如果直接在线程里更新UI会报错,报“从不是创建控件lable1的线程访问它”,为什么会报这个错呢?这个问题就是跨线程访问控件问题,窗体上的控件只允许创建它们的线程访问,也就是主线程(UI线程),如果非主线程访问则会发生异常我们看到会报错,且这个错误是“从不是创建控件lable1的线程访问它”
TestClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace WindowsFormsApplication1
{
public class TestClass
{
//声明一个delegate(委托)类型:TestDelegate,该类型可以搭载返回值为空,参数只有一个(long型)的方法。
public delegate void TestDelegate(long i); //声明一个TestDelegate类型的对象。该对象代表了返回值为空,参数只有一个(long型)的方法。它可以搭载N个方法。
public TestDelegate mainThread; /// 测试方法
/// <summary>
/// </summary>
public void TestFunction()
{
long i = ;
while (true)
{
i++;
mainThread(i); //调用委托对象
Thread.Sleep(); //线程等待1000毫秒
}
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
//创建TestClass类的对象
TestClass testClass = new TestClass(); //在testclass对象的mainThread(委托)对象上搭载两个方法,在线程中调用mainThread对象时相当于调用了这两个方法。
testClass.mainThread = new TestClass.TestDelegate(RefreshLabMessage1);
testClass.mainThread += new TestClass.TestDelegate(RefreshLabMessage2); //创建一个无参数的线程,这个线程执行TestClass类中的TestFunction方法。
Thread testClassThread = new Thread(new ThreadStart(testClass.TestFunction));
//启动线程,启动之后线程才开始执行
testClassThread.Start();
} /// <summary>
/// 在界面上更新线程执行次数
/// </summary>
/// <param name="i"></param>
private void RefreshLabMessage1(long i)
{
//判断该方法是否被主线程调用,也就是创建labMessage1控件的线程,当控件的InvokeRequired属性为ture时,说明是被主线程以外的线程调用。如果不加判断,会造成异常
if (this.labMessage1.InvokeRequired)
{
//再次创建一个TestClass类的对象
TestClass testclass = new TestClass();
//为新对象的mainThread对象搭载方法
testclass.mainThread = new TestClass.TestDelegate(RefreshLabMessage1);
//this指窗体,在这调用窗体的Invoke方法,也就是用窗体的创建线程来执行mainThread对象委托的方法,再加上需要的参数(i)
this.Invoke(testclass.mainThread, new object[] { i });
}
else
{
labMessage1.Text = i.ToString();
}
} /// <summary>
/// 在界面上更新线程执行次数
/// </summary>
/// <param name="i"></param>
private void RefreshLabMessage2(long i)
{
//同上
if (this.labMessage2.InvokeRequired)
{
//再次创建一个TestClass类的对象
TestClass testclass = new TestClass();
//为新对象的mainThread对象搭载方法
testclass.mainThread = new TestClass.TestDelegate(RefreshLabMessage2);
//this指窗体,在这调用窗体的Invoke方法,也就是用窗体的创建线程来执行mainThread对象委托的方法,再加上需要的参数(i)
this.Invoke(testclass.mainThread, new object[] { i });
}
else
{
labMessage2.Text = i.ToString();
}
}
}
}
执行效果
C#新开一个线程取到数据,如何更新到主线程UI上面的更多相关文章
- java的服务是每收到一个请求就新开一个线程来处理吗?tomcat呢?
首先,服务器的实现不止有这两种方式. 先谈谈题主说的这两种服务器模型: 1.收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会 ...
- BeginInvoke 方法真的是新开一个线程进行异步调用吗?
转自原文BeginInvoke 方法真的是新开一个线程进行异步调用吗? BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void tre ...
- [转]MFC子线程更改图像数据后更新主窗口图像显示方法
程序思路是由外部的输入输出控制卡发出采集图像信号,之后相机采集图像得到图像数据指针,接收图像数据指针创建成图像最后显示到MFC对话框应用程序的Picture Control控件上,同时,为了标定相机位 ...
- WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)
最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...
- Python+Selenium练习篇之15-在浏览器中新开一个tab
本文介绍如selenium方法打开一个新的tab,我们知道在浏览器里,我们按住 ctrl+ t 就可以新打开一个tab.所以我们学习如何利用webdriver中send_key 的方法去触发ctrl+ ...
- SQL存在一个表而不在另一个表中的数据, 更新字段为随机时间
--更新字段为随机时间 86400秒=1天 UPDATE dl_robot ), ,GETDATE()) ) SQL存在一个表而不在另一个表中的数据 方法一 使用 not in ,容易理解,效 ...
- 开源一个爬取redmine数据的测试报告系统
背景 软件测试的最后有一道比较繁琐的工作,就是编写测试报告.手写测试报告在数据统计和分析上面要耗费比较大的事件和精力.之前工作室使用mantis管理bug缺陷.公司有内部有个系统,可以直接从manti ...
- shell脚本,怎么实现每次新开一个shell都输出一个提示语?
[root@localhost wyb]# cat test.sh echo -e "\033[32mhello,This is wangyuebo's shell\033[0m" ...
- 怎么新开一个组件并且配置路由?vue-cli
首先要明白: 路由就是url路径,如果一个组件被引入到了另外一个组件,这个页面就包含这个组件了,所以这个被包含的组件不要去路由哪里配置了 第一步: 先写上想要添加的组件 2.组件的内容 3.路由的配置 ...
随机推荐
- 【07_226】Invert Binary Tree
Invert Binary Tree Total Accepted: 54994 Total Submissions: 130742 Difficulty: Easy Invert a binary ...
- JS判断手机访问跳转到手机站
这里提供了六种让手机端访问网站跳转到手机端的方法: 第一种: <script> if(navigator.platform.indexOf('Win32')!=-1){ //pc //wi ...
- git 使用笔记
git操作: git checkout 分支名称 // 切换分支git branch -a // 查看分支信息和当前分支 git pull // 将服务器所有代码下载到本地git merge orig ...
- 利用dbms_metadata.get_ddl查看DDL语句
http://www.cnblogs.com/aocle/archive/2011/10/13/2209790.html 当我们想要查看某个表或者是表空间的DDL的时候,可以利用dbms_metada ...
- 揭秘Sql2014新特性-tempdb性能提升
一直以来,在高负载,复杂的生产环境中,tempdb的压力是成为整个实例瓶颈的重要因素之一.微软的工程师们也在各个版本中不断优化它的使用.到了Sql Server2014又有了新的特性使其性能得temp ...
- C#设计模式(5)——建造者模式(Builder Pattern)
一.引言 在软件系统中,有时需要创建一个复杂对象,并且这个复杂对象由其各部分子对象通过一定的步骤组合而成.例如一个采购系统中,如果需要采购员去采购一批电脑时,在这个实际需求中,电脑就是一个复杂的对象, ...
- NodeJS package.json
#3 NodeJS package.json 工作目录 package.json 导航至工作目录后,执行下图中的命令
- 通过Anuglar Material串串学客户端开发 - NodeJS模块机制之Module.Exports
module.exports 前文讲到在Angular Material的第二个编译文件docs/gulpfile.js中却看到了一个奇怪的东西module.exports那么module.expor ...
- 简洁清新的box样式
小菜今天偶然打开了腾讯公益,本来是冲着公益活动去的,没想到腾讯公益界面做的还不错,索性把它的box样式剽窃了下来. 个人觉得腾讯的东西普遍比较精致,就拿页面来说,每一个细节都把握的很到位,例如取色,看 ...
- BlueDream.js(蓝梦)——jQuery网站使用引导插件
小菜在前端世界游荡有些时间了,常见的插件多少有些了解,但却很少看到用户引导插件. 所谓用户引导插件,就是在第一次使用某个网站时,会弹出一些小动画,告诉你网站的基本使用方法,帮你快速入门. 这应该是个常 ...