一:问题
  
之前有被面试官问过,在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上面的更多相关文章

  1. java的服务是每收到一个请求就新开一个线程来处理吗?tomcat呢?

    首先,服务器的实现不止有这两种方式. 先谈谈题主说的这两种服务器模型: 1.收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会 ...

  2. BeginInvoke 方法真的是新开一个线程进行异步调用吗?

    转自原文BeginInvoke 方法真的是新开一个线程进行异步调用吗? BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void tre ...

  3. [转]MFC子线程更改图像数据后更新主窗口图像显示方法

    程序思路是由外部的输入输出控制卡发出采集图像信号,之后相机采集图像得到图像数据指针,接收图像数据指针创建成图像最后显示到MFC对话框应用程序的Picture Control控件上,同时,为了标定相机位 ...

  4. WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)

    最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...

  5. Python+Selenium练习篇之15-在浏览器中新开一个tab

    本文介绍如selenium方法打开一个新的tab,我们知道在浏览器里,我们按住 ctrl+ t 就可以新打开一个tab.所以我们学习如何利用webdriver中send_key 的方法去触发ctrl+ ...

  6. SQL存在一个表而不在另一个表中的数据, 更新字段为随机时间

    --更新字段为随机时间 86400秒=1天 UPDATE dl_robot ), ,GETDATE()) )   SQL存在一个表而不在另一个表中的数据   方法一 使用 not in ,容易理解,效 ...

  7. 开源一个爬取redmine数据的测试报告系统

    背景 软件测试的最后有一道比较繁琐的工作,就是编写测试报告.手写测试报告在数据统计和分析上面要耗费比较大的事件和精力.之前工作室使用mantis管理bug缺陷.公司有内部有个系统,可以直接从manti ...

  8. shell脚本,怎么实现每次新开一个shell都输出一个提示语?

    [root@localhost wyb]# cat test.sh echo -e "\033[32mhello,This is wangyuebo's shell\033[0m" ...

  9. 怎么新开一个组件并且配置路由?vue-cli

    首先要明白: 路由就是url路径,如果一个组件被引入到了另外一个组件,这个页面就包含这个组件了,所以这个被包含的组件不要去路由哪里配置了 第一步: 先写上想要添加的组件 2.组件的内容 3.路由的配置 ...

随机推荐

  1. 【原创】-- uboot,kennel,fs,rootfs 编译制作

    环境:ubuntu14.04  内核版本 linux 3.13.0   OK6410 内核编译环境   linux 3.0.1 uboot版本    1.1.6   交叉编译工具链   arm-lin ...

  2. hdu - 3952 Fruit Ninja(简单几何)

    思路来自于:http://www.cnblogs.com/wuyiqi/archive/2011/11/06/2238530.html 枚举两个多边形的两个点组成的直线,判断能与几个多边形相交 因为最 ...

  3. java获取classpath文件路径空格转变成了转义字符%20的问题

    java获取classpath文件路径空格转变成了转义字符%20的问题 这个问题很纠结,服务器的文件路径带有空格,空格被转化是%20了,悲剧就出现了 下面展示一段代码String path = get ...

  4. Xamarin开发Android笔记:背景操作

    使用Xamarin开发Android UI的时可能会遇到一些场景背景的问题,虽然可以利用多层或直接使用图片背景来完成,但这样会增加不少的资源消耗,最终导致内存溢出的情况.最好的方法还是利用内部方法或代 ...

  5. C#结合LumiSoft.Net.dll读取Outlook邮件(.eml格式邮件)

    如果直接从Outlook(或者微软的其它邮件客户端如:Outlook Express.Windows Live Mail)的邮件文件(.eml格式)中提取各种电子邮件内容,使用LumiSoft.Net ...

  6. 设计模式之美:Facade(外观)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):用抽象类定义 Facade 而使子类对应于不同的子系统. 意图 为子系统中的一组接口提供一个一致的界面,Facade 模式定义了 ...

  7. javascript高级程序设计阅读笔记(一)

    javascript高级程序设计阅读笔记(一) 工作之余开发些web应用作为兴趣,在交互方面需要掌握javascript和css.HTML5等技术,因此读书笔记是必要的. javascript简介 J ...

  8. [游戏模版1] MFC最小框架(base function including)

    >_<:Here are the template of mini-MFC include: CPen,CBrush,Front,Paint Line and some other gra ...

  9. Nutz Dao实体中索引注解的使用(@TableIndexes@Index)

    Nutz是一组轻便小型的框架的集合, 各个部分可以被独立使用,把SSH的精华封装在一个1M左右的jar包中,Nutz不对其他任何第三方库产生依赖,如果不考虑数据库链接和日志的话,创建完美的Web应用只 ...

  10. web app 禁用手机浏览器缓存方法

    开发过web app的同学,特别是前端人员,都碰到这烦人的事情,JS或CSS代码改变,可手机浏览器怎么刷新都不更新,手机浏览器的缓存特别恶劣. 所以今天贴个方法解决这问题.记得,本地调试的时候贴上,上 ...