当前位置: 首页 > 编程日记 > 正文

C#WinForm的线程及Invoke应用(转)

C#多线程异步访问winform中控件  

http://zwkufo.blog.163.com/blog/static/25882512009111453957552/?fromdm&fromSearch&isFromSearchEngine=yes

我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。

首先来看传统方法:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(ThreadFuntion);
            thread.IsBackground = true;
            thread.Start();
        }
        private void ThreadFuntion()
        {
            while (true)
            {
                this.textBox1.Text = DateTime.Now.ToString();
                Thread.Sleep(1000);
            }
        }
    }

运行这段代码,我们会看到系统抛出一个异常:Cross-thread operation not valid:Control 'textBox1' accessed from a thread other than the thread it was created on . 这是因为.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。那么怎么解决这个问题呢,下面提供几种方案。

第一种方案,我们在Form1_Load()方法中加一句代码:

private void Form1_Load(object sender, EventArgs e)
       {
            Control.CheckForIllegalCrossThreadCalls = false;
            Thread thread = new Thread(ThreadFuntion);
            thread.IsBackground = true;
            thread.Start();
        }
      加入这句代码以后发现程序可以正常运行了。这句代码就是说在这个类中我们不检查跨线程的调用是否合法(如果没有加这句话运行也没有异常,那么说明系统以及默认的采用了不检查的方式)。然而,这种方法不可取。我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。而且像这种跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了,我们要采取另外的方案。

下面来看第二种方案,就是使用delegate和invoke来从其他线程中控制控件信息。网上有很多人写了这种控制方式,然而我看了很多这种帖子,表明上看来是没有什么问题的,但是实际上并没有解决这个问题,首先来看网络上的那种不完善的方式:

public partial class Form1 : Form
    {
        private delegate void FlushClient();//代理
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(CrossThreadFlush);

thread.IsBackground=true;
            thread.Start();
        }

private void CrossThreadFlush()
        {
            //将代理绑定到方法
            FlushClient fc = new FlushClient(ThreadFuntion);
            this.BeginInvoke(fc);//调用代理
        }
        private void ThreadFuntion()
        {
            while (true)
            {
                this.textBox1.Text = DateTime.Now.ToString();
                Thread.Sleep(1000);
            }
        }
    }

使用这种方式我们可以看到跨线程访问的异常没有了。但是新问题出现了,界面没有响应了。为什么会出现这个问题,我们只是让新开的线程无限循环刷新,理论上应该不会对主线程产生影响的。其实不然,这种方式其实相当于把这个新开的线程“注入”到了主控制线程中,它取得了主线程的控制。只要这个线程不返回,那么主线程将永远都无法响应。就算新开的线程中不使用无限循环,使可以返回了。这种方式的使用多线程也失去了它本来的意义。

现在来让我们看看推荐的解决方案:

public partial class Form1 : Form
    {
        private delegate void FlushClient();//代理
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(CrossThreadFlush);
            thread.IsBackground = true;
            thread.Start();
        }

private void CrossThreadFlush()
        {
            while (true)
            {
                //将sleep和无限循环放在等待异步的外面
                Thread.Sleep(1000);
                ThreadFunction();
            }
        }
        private void ThreadFunction()
        {
            if (this.textBox1.InvokeRequired)//等待异步
            {
                FlushClient fc = new FlushClient(ThreadFunction);
                this.Invoke(fc);//通过代理调用刷新方法
            }
            else
            {
                this.textBox1.Text = DateTime.Now.ToString();
            }
        }
    }

运行上述代码,我们可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程对winform多线程控件的控制了。

转载于:https://www.cnblogs.com/yjg8116/archive/2011/12/22/2298398.html

相关文章:

C/C++语言点滴

C/C学习笔记 1.C语言中使用关键字sizeof来求数组长度 char temp[3]; int tempLen sizeof(temp)/sizeof(char); strlen只能用来求字符串长度 2.交换两个数据的几种方法及其区别 方法一:值传递,在main函数中并未改变a,b 的值,虽然在swap中a…

[C#][EF] 添加表添加不进来

确认此表有没有主键,没有主键时就会这样。转载于:https://www.cnblogs.com/z5337/p/8891230.html

DNN 数据访问策略 (转)

经过几天断断续续的努力,这篇文章终于翻译结束,文章主要讲了DNN的数据访问策略,对于了解系统整体上是如何工作的有一定的帮助,希望能给dnn的初学者一些有用的信息。由于翻译的匆忙水平有限,错误或不当之处在所难免&…

Windows程序设计学习笔记(1):一个简单的windows程序

《Windows程序设计》(第五版)(美Charles Petzold著) 1 #include<windows.h>2 3 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);4 5 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdline,int iCmdShow) 6 //第一个参数是实例句柄&#…

【二级java】模拟题知识点总结

算法的复杂度 &#xff1a; &#xff08;一&#xff09;时间复杂度 &#xff1a; 执行算法所需要的计算工作量&#xff0c;与计算机的运行速度和存储空间无关 &#xff08;二&#xff09;空间复杂度 &#xff1a; 算法在运行过程中临时占用的存储空间的大小。 零散知识点 &am…

虚拟化市场成熟

调查称虚拟化市场已经成熟 VMware份额领先 存储在线 11年03月18日 WangFei 导读&#xff1a;据市场研究公司Forrester Research最新研究表明&#xff0c;虚拟服务器技术的应用实际上是从去年开始的&#xff0c;虚拟服务器技术终于完成了测试和研发阶段。 关键词&#xff1a…

python day two,while

一、运算符号 算数运算符&#xff1a; 、-、*、/、//&#xff08;取整除&#xff09;、%&#xff08;去余&#xff09;、** 比较运算符&#xff1a;>、< 、>、<、 赋值运算符&#xff1a;、、-、/、%、** 逻辑预算符&#xff1a;and、or、not 布尔值 成员运算符&am…

【模板】树状数组 2

题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 1.将某区间每一个数数加上x 2.求出某一个数的值 输入输出格式 输入格式&#xff1a; 第一行包含两个整数N、M&#xff0c;分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格…

【java】Maven工程引入各种jar包的功能

1、mysql驱动 &#xff1a; 代码实现 &#xff1a; <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>6.0.6</version></dependency> 2、数据库操作工具 &#xff1a; 代码实现…

[转]Android横竖屏切换解决方案

本文转自&#xff1a;http://www.cnblogs.com/domybest/archive/2011/06/30/2094779.html 首先在Mainifest.xml的Activity元素中加入android:configChanges"orientation|keyboardHidden"属性<activity android:name".FileBrowser" android:label"s…

【百度地图API】——国内首款团购网站的地图插件

摘要&#xff1a; 本文介绍了一款应用在团购网站上的地图插件&#xff0c;适用于目前非常流行的团购网站。使用这款地图插件&#xff0c;无需任何编程技术&#xff0c;你就把商家的位置轻松地标注在地图上。 前台地址 http://map.baidu.com/fwmap/upload/r/map/fwmap/tuangou/u…

Wannafly挑战赛14

A.直角三棱锥 枚举推式子 1 #include <bits/stdc.h>2 using namespace std;3 typedef long long LL;4 LL gcd(LL a, LL b){5 return a % b ? gcd(b, a % b) : b;6 }7 int main(){8 int T;9 scanf("%d", &T); 10 while(T--) { 11 …

第八章 泛型程序设计

1.带有【超类型限定 super】的通配符可以向泛型对象写入&#xff0c;带有【子类型限定 extends】的通配符可以从泛型对象读取&#xff0c;反之则不然。转载于:https://www.cnblogs.com/baokang/p/7441122.html

【java】过滤器filter的使用

一、创建filter的实现类 代码实现 &#xff1a; package com.zzxtit.common.filter;import java.io.IOException;import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax…

简单统计分数的程序

//设计一个程序&#xff0c;统计某个班级某门考试成绩中的最高分、最低分和平均分。 //当输入分数为-1时&#xff0c;输入结束 #include<iostream> using namespace std; int main() { int value,total,max,min,noOfInput; total0; //总分 max0; min100; noOfInput0; //人…

SugarCRM ListView查询中加入默认条件

在$_REQUEST[where] $where;$storeQuery->process_views($currentModule);上面加入以下代码,下面的代码指默认为查询本月if($where){ $date_period thismonth; $date_from get_date_from($date_period); $date_to get_date_to($date_period); if(isset($date_from) &…

Vue2.0使用vue-cli脚手架搭建

一&#xff1a;安装node.js Node.js官网&#xff1a;https://nodejs.org/en/download/ 选择相应的版本即可安装 通过node自带的npm包管理工具 二、安装依赖 安装依赖&#xff1a;npm install 如果国外安装比较慢&#xff0c;可采用国内淘宝镜像安装&#xff1a;npm install -g …

【javaweb】eclipse重启后tomcat打不开解决方法

https://blog.csdn.net/enniexiaorui/article/details/70161040

编写高性能的 JavaScript 程序的几个提示

2019独角兽企业重金招聘Python工程师标准>>> 这是一篇来自国外的文章&#xff0c;从各个方面介绍如何编写一个高性能的 JavaScript 应用程序。例如应该在页面最底部加载JS文件、合并多个js文件、异步加载js文件等等。 全文阅读&#xff08;英文&#xff09; 转载于:…

[网络流24题] 最长k可重区间集

对于区间 u->v &#xff0c;连接边 u->v&#xff0c;权值为-len&#xff0c;容量为1&#xff0c;之后对每个点 i->i1&#xff0c;连边 i->i1&#xff0c;容量为k&#xff0c;权值为0&#xff0c;求区间最左端点到最右端点的费用流&#xff0c;费用相反数即为答案。…

Gym - 102082G

Gym - 102082Ghttps://vjudge.net/problem/2198225/origin对于数列中任意一个数&#xff0c;要么从最左边到它不递减&#xff0c;要么从最右边到到它不递减&#xff0c;为了满足这个条件&#xff0c;就要移动&#xff0c;而移动的最少步数就是逆序对数。所以这个数要么往左移动…

JAVA环境变量配置与配置后CMD的使用

JAVA环境变量配置&#xff1a; 直接在环境变量Path(或PATH&#xff0c;大小写无所谓)里加上 &#xff1a;JDK安装路径名/bin 也可以先设JAVA_HOME然后再设JAVA_HOME/bin&#xff0c;但必须是在同一区域中进行设置&#xff0c;系统变量区域或用户变量区域&#xff0c;否则设置的…

【web】从数据库读取多条数据到前台

servlet 代码实现 &#xff1a; package com.zzxtit.order;import java.io.IOException; import java.sql.SQLException; import java.util.List;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet…

FUSE——用户空间文件系统

用户空间文件系统&#xff08;Filesystem in Userspace&#xff0c;简称FUSE&#xff09;是操作系统中的概念&#xff0c;指完全在用户态实现的文件系统。目前Linux通过内核模块对此进行支持。一些文件系统如ZFS&#xff0c;glusterfs和luster使用FUSE实现。       Linux…

29个简单直观的移动设备网页设计

毫无疑问的是移动网络已经风靡世界。运行在iOS或Android智能手机&#xff0c;这两者提供了出色的网页浏览平台。而且这个数字仅仅是预期增加人口的平均工资增长率扩大。 然而该过程的设计和编码移动模板可以是非常乏味。我希望提供一个创造性的思路在这个画廊29个直观的手机设计…

【java】maven工程使用switch时不能使用String解决方法

原因 &#xff1a; 1.7之前不支持使用String 解决方法 &#xff1a; 1、右击程序------》 Build Path ------》Config Build Path 2、选择图示选项 3、更改选项&#xff0c;如图 4、更改编译器 5、将版本改为1.8 6、应用

Oracle 存储过程 无法编译 解决方法(转载)

声明:本文为转载,如果有侵犯知识版本&#xff0c;请通知本人&#xff0c;本人将即刻停止侵权行为: http://blog.csdn.net/tianlesoftware/article/details/7412555 Oracle存储过程无法编译&#xff0c;在PL/SQL中编译&#xff0c;总是挂住了&#xff0c;这个原因可能是要编译的…

交流一点CCNP学习经验

首先反问自己&#xff0c;学习NP的最现实目的是什么。 如果是在校大学生&#xff0c;中专&#xff0c;职高的学生。大多目的是通过一个认证&#xff0c;学习更多有用的知识和技能。招个好工作。有个好的开始。这样应该是把扎实的基础理论和熟练的基础实验操作放在第一位。不要死…

iOS测试基础(命令篇)-iPhone型号及其他信息

首先安装libimobiledevice和ideviceinstaller brew uninstall ideviceinstaller brew uninstall libimobiledevice brew install --HEAD libimobiledevice brew link --overwrite libimobiledevice brew install ideviceinstaller brew link --overwrite ideviceinstaller 应用…

Soft-to-Hard Vector Quantization for End-to-End Learning Compressible Representations

郑重声明&#xff1a;原文参见标题&#xff0c;如有侵权&#xff0c;请联系作者&#xff0c;将会撤销发布&#xff01; Abstract: 我们提出了一种新的方法&#xff0c;通过端到端的训练策略来学习深度架构中的可压缩表征。我们的方法是基于量化和熵的软&#xff08;连续&#x…