在C#中子线程如何操作主窗口线程上的控件
在C#中子线程怎样操作主线程中窗口上控件
在C#中,直接在子线程中对窗口上的控件操作是会出现异常,这是因为子线程和运行窗口的线程是不同的空间,因此想要在子线程来操作窗口上的控件。是不可能简单的通过控件对象名来操作,但不是说不能进行操作,微软提供了Invoke的方法。其作用就是让子线程告诉窗口线程来完毕对应的控件操作。
要实现该功能,基本思路例如以下:
把想对还有一线程中的控件实施的操作放到一个函数中,然后使用delegate代理那个函数。而且在那个函数中加入一个推断,用 InvokeRequired 来推断调用这个函数的线程是否和控件线程处于同一线程中,假设是则直接运行对控件的操作。否则利用该控件的Invoke或BeginInvoke方法来运行这个代理。
演示样例代码例如以下:
1 using System;
2 using System.Collections.Generic;
3 using System.Windows.Forms;
4
5 using System.Threading;
6
7 namespace 子线程操作主线程窗口上的控件
8 {
9 public partial class frmMain : Form
10 {
11 /********************** 定义该类的私有成员 **************************/
12
13 /// <summary>
14 /// 定义一个队列,用于记录用户创建的线程
15 /// 以便在窗口关闭的时候关闭全部用于创建的线程
16 /// </summary>
17 private List<Thread> ChaosThreadList;
18
19 /********************** 该类的初始化相关函数 ************************/
20
21 /// <summary>
22 /// 窗口的初始化函数,初始化线程队列ChaosThreadList
23 /// </summary>
24 public frmMain()
25 {
26 InitializeComponent();
27 ChaosThreadList = new List<Thread>();
28 }
29
30 /// <summary>
31 /// 窗口的关闭事件处理函数。在该事件中将之前创建的线程全部终止
32 /// </summary>
33 /// <param name="sender"></param>
34 /// <param name="e"></param>
35 private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
36 {
37 if (ChaosThreadList.Count > 0)
38 {
39 //编列自己定义队列,将全部线程终止
40 foreach (Thread tWorkingThread in ChaosThreadList)
41 {
42 tWorkingThread.Abort();
43 }
44 }
45 }
46
47 /**************************** 定义该类的自己定义函数 ***********************/
48
49 /// <summary>
50 /// 定义一个代理
51 /// </summary>
52 /// <param name="index"></param>
53 /// <param name="MSG"></param>
54 private delegate void DispMSGDelegate(int index,string MSG);
55
56 /// <summary>
57 /// 定义一个函数。用于向窗口上的ListView控件加入内容
58 /// </summary>
59 /// <param name="iIndex"></param>
60 /// <param name="strMsg"></param>
61 private void DispMsg(int iIndex,string strMsg)
62 {
63 if (this.lstMain.InvokeRequired==false) //假设调用该函数的线程和控件lstMain位于同一个线程内
64 {
65 //直接将内容加入到窗口的控件上
66 ListViewItem lvi = new ListViewItem();
67 lvi.SubItems[0].Text = iIndex.ToString();
68 lvi.SubItems.Add(strMsg);
69 this.lstMain.Items.Insert(0, lvi);
70 }
71 else //假设调用该函数的线程和控件lstMain不在同一个线程
72 {
73 //通过使用Invoke的方法,让子线程告诉窗口线程来完毕对应的控件操作
74 DispMSGDelegate DMSGD = new DispMSGDelegate(DispMsg);
75
76 //使用控件lstMain的Invoke方法运行DMSGD代理(其类型是DispMSGDelegate)
77 this.lstMain.Invoke(DMSGD, iIndex, strMsg);
78
79 }
80 }
81
82 /// <summary>
83 /// 定义一个线程函数,用于循环向列表中加入数据
84 /// </summary>
85 private void Thread_DisplayMSG()
86 {
87 for (int i = 0; i < 10000; i++)
88 {
89 DispMsg(i + 1, "Welcome you : " + (i + 1).ToString());
90 Thread.Sleep(10);
91 }
92 }
93
94 /******************************* 定义该类的事件处理函数 ********************************/
95
96 /// <summary>
97 /// 【開始】button的单击事件处理函数,新建一个线程向窗口上的ListView控件填写内容
98 /// </summary>
99 /// <param name="sender"></param>
100 /// <param name="e"></param>
101 private void btnBegin_Click(object sender, EventArgs e)
102 {
103 //创建一个新的线程
104 Thread tWorkingThread = new Thread(Thread_DisplayMSG);
105
106 //将新建的线程加入到自己定义线程队列中,以便在窗口结束时关闭全部的线程
107 ChaosThreadList.Add(tWorkingThread);
108
109 //开启线程
110 tWorkingThread.Start();
111 }
112
113 }
114 }
这样子就能够实现用子线程去操作主线程窗口上的控件的内容,同一时候,又不影响主线程对窗口上其他控件的响应。程序运行截图例如以下:
点击[開始]button,程序开启一个新的线程,不断向列表中加入新的数据。而同一时候不会影响主界面对其他控件(比如:文本框)的响应。
[P.S]:
INVOKE方法的作用:
它允许在那里运行的线程控制Invoke在代理指定的方法参数。这是我们要控制的操作执行的主线程运行。
在C#中子线程如何操作主窗口线程上的控件的更多相关文章
- C#定义委托函数实现在别的窗体中操作主窗体中的SerialPort控件
1.在主窗体(含有serialPort的窗体)中 //先定义委托 public delegate void OpenPort(); public delegate void ClosePort(); ...
- [Winform]线程间操作无效,从不是创建控件的线程访问它的几个解决方案,async和await?
目录 概述 取消跨线程检查 使用委托异步调用 sync和await 总结 概述 最近在qq群里有一朋友,问起在winform中怎么通过开启线程的方式去处理耗时的操作,比如,查看某个目录下所有的文件,或 ...
- 用委托在listbox中异步显示信息,解决线程间操作无效,从不是创建控件的线程访问它
//创建一个委托,是为访问listbox控件服务的. public delegate void UpdateTxt(string msg); //定义一个委托变量 public UpdateTxt u ...
- WPF 程序如何跨窗口/跨进程设置控件焦点
原文:WPF 程序如何跨窗口/跨进程设置控件焦点 WPF 程序提供了 Focus 方法和 TraversalRequest 来在 WPF 焦点范围内转移焦点.但如果 WPF 窗口中嵌入了其他框架的 U ...
- C# winform中使用Panel调节窗口变化是各控件的位置(转)
我的目的是在窗口上有些控件,在窗口大小变化时,上面的控件位置不动,大小也不动.下面的控件随着窗口的大小变化而变大. 做法是用两个panel,panelTop和panelFill.上面的控件都放到pan ...
- WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)
最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...
- Python pyQt4/pyQt5 学习笔记1(空白窗口,按钮,控件事件,控件提示,窗体显示到屏幕中间,messagebox)
PyQt4是用来编写有图形界面程序(GUI applications)的一个工具包.PyQt4作为一个Python模块来使用,它有440个类和超过6000种函数和方法.同时它也是一个可以在几乎所有主流 ...
- 【问题解决】线程间操作无效:从不是创建控件“textBox1”的线程访问它
背景 通过一个辅助线程计算出的一个值赋给textBox1.text: 解决办法 1.直接在窗体的构造函数中添加: System.Windows.Forms.Control.CheckForIllega ...
- C语言Windows程序开发—Windows窗口样式与常用控件样式【第04天】
(一)Windows窗口(MDICLIENT)样式介绍 /* Windows窗口样式 */ WS_BORDER //带有边框的窗口 WS_CAPTION //带有标题栏的窗口 WS_CHILD //子 ...
随机推荐
- 【每日一摩斯】-Troubleshooting: High CPU Utilization (164768.1) - 系列5
Oracle(用户)进程 以下这些操作都是需要消耗大量CPU资源的:解析大型查询,存储过程编译或执行,空间管理和排序. 下面这几篇文章可以帮助采集关于使用高CPU资源的进程的更多信息: Note:35 ...
- RFS的web自动化验收测试——第14讲 万能的evaluate
引言:什么是RFS——RobotFramework+Selenium2library,本系列主要介绍web自动化验收测试方面. ( @齐涛-道长 新浪微博) 这一讲我们重点来介绍一下一个常用的关键字e ...
- Swift - iOS应用的国际化与本地化
在Xcode中我们可以很方便的将APP适配各种本地化语言.苹果的框架已经帮我们把不同语言的数据分离开,包括图片,声音,视频,文档,用户界面文字(甚至代码中编写的用户界面文字),它们会被建立在同一个bu ...
- JENKINS 打包发布脚本
#!/bin/bash #nohup bash check_new_pkgs_dev.sh & #steps below: ##发布的机器上运行这个脚本 #定时遍历发布包存放路径 #1.遍历所 ...
- 基于visual Studio2013解决C语言竞赛题之1084完全平方数
题目 解决代码及点评 /************************************************************************/ /* ...
- 单链表的插入删除操作(c++实现)
下列代码实现的是单链表的按序插入.链表元素的删除.链表的输出 // mylink.h 代码 #ifndef MYLINK_H #define MYLINK_H #include<iostream ...
- 远光软件ASP.NET笔试题小汇总
ASP.NET笔试题是ASP.NET程序员面试必须经历的,一般会叫你填两个表 1个是你的详细信息表 1个是面试题答卷 两个都要注意反正面是否都有内容不要遗漏,如果考你机试一般也有两种,就是程序连接数据 ...
- Effective C++_笔记_条款04_确定对象被使用之前已先被初始化
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 读取未初始化的值会导致不确定的行为.在某些平台上,仅仅只是读取为 ...
- TCP与UDP各自特点对比
UDP和TCP是我们最常用的两种通信方式,下面就两者之间的特点做一个对比: 1.UDP主要用在实时性要求高以及对质量相对较弱的地方,如流媒体. 2.TCP既然是面向连接的,那么运行环境必然要求其保证可 ...
- 关于iOS7以后版本号企业公布问题
大家都知道,苹果在公布7.1以后,不打个招呼就把企业公布方式给换掉了(谴责一下~) 曾经普通server+web页面+ipa+plist就能够搞定,如今已经不行了. 关于如今企业公布教程网上贴出来了非 ...