C# 线程thread

摘要:
控件在主线程中创建。主线程控制直接在其他线程中访问,并且与主线程发生线程冲突。如果控件的Handle是在与调用线程不同的线程上创建的,则为true;否则,这是错误的。

一、问题总结

 1. 在WinForm开发过程中用到线程时,往往需要在线程中访问线程外的控件,比如:设置textbox的Text值等等。如果直接访问UI控件会报出“从不是创建控件的线程访问它”错误。控件是在主线程中创建的(比如this.Controls.Add(...);),在其它线程直接访问主线程控件,与主线程发生线程冲突。

解决方法:

在控件响应函数中调用控件的Invoke方法,Invoke方法会顺着控件树向上搜索,直到找到创建控件的那个线程(通常是主线程),然后进入那个线程改变控件的外观,确保不发生线程冲突。

MSDN中说:
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
如果控件的 Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性 。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。   

2. invoke表示同步,begininvoke表示异步。

3.在使用invoke前,判断IsHandleCreated 此属性指示控件是否有与他关联的句柄,如果已经为控件分配了句柄,则为 true;否则为 false。

 加此判断可以避免在退出程序的时候,如果此时调用了invoke中的控件,就会出现错误“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”

二、代码举例

 1.线程访问主线程控件  

using System;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(new ThreadStart(DoWork));
            th.Start();         

        }     
        private void DoWork()
        {          
            ShowMsg("hello world");           
        }

        delegate void ShowMsgDelegate(string msg); 
        //普通委托
        private void ShowMsg(string msg)
        {
            if(lblMsg.InvokeRequired)
            {
                ShowMsgDelegate showMsgDelegate = new ShowMsgDelegate(ShowMsg);
                lblMsg.Invoke(showMsgDelegate, new object[] { msg });
            }
            else
            {
                lblMsg.Text = msg;
            }           

        }

        //匿名代理
        private void ShowMsg2(string msg)
        {
            ShowMsgDelegate showMsgDelegate = delegate (string str)
            {
                lblMsg.Text = str;
            };
            lblMsg.Invoke(showMsgDelegate, new object[] { msg });

        }

        //在C# 3.0及以后的版本中有了Lamda表达式,
        //像上面这种匿名委托有了更简洁的写法。
        private void ShowMsg3(string msg)
        {
            this.Invoke(new Action(() => {
                lblMsg.Text = msg;
            }
            ));
        }

       
    }
}
 
 private void ShowMsg(string msg, bool isOk)
        {
            if (this.IsHandleCreated)
            {
                this.Invoke(new Action(() =>
                {
                    lblMsg.Text = msg;
                    lblMsg.ForeColor = isOk ? Color.Green : Color.Red;                  

                }));
            }
        }

lambda写法

  private void button1_Click(object sender, EventArgs e)
        {
            Console.WriteLine("start");
            testThread =new Thread(() =>{

                for(int i=0;i<20;i++)
                {
                    Console.WriteLine(i);
                }
               
            });
            testThread.Start();
            Console.WriteLine("end");
        }

执行结果:

start
end
0
1
2
3
4
5
6
7
8
9

免责声明:文章转载自《C# 线程thread》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vim利用coc补全的配置过程css3实现倾斜转动的转盘下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

GDB常用调试命令以及多进程多线程调试

http://blog.csdn.net/freeelinux/article/details/53700266 一:普通命令   1.list命令 list  linenum      显示程序第linenum行周围的程序 list  function      显示函数名为function的函数的源程序 list                  ...

Java多线程-线程的调度(休眠)

Java线程调度是Java多线程的核心,只有良好的调度,才能充分发挥系统的性能,提高程序的执行效率。这里要明确的一点,不管程序员怎么编写调度,只能最大限度的影响线程执行的次序,而不能做到精准控制。线程休眠的目的是使线程让出CPU的最简单的做法之一,线程休眠时候,会将CPU资源交给其他线程,以便能轮换执行,当休眠一定时间后,线程会苏醒,进入准备状态等待执行。...

读写锁

(1) 读写锁是几把锁   一把锁   pthread_rwlock_t lock; (2) 读写锁的类型   读锁: 对内存做读操作   写锁: 对内存做写操作 (3) 读写锁的特性:   线程A加读锁成功, 又来了三个线程, 做读操作, 可以加锁成功     读共享, 并行处理   线程A加写锁成功, 又来了三个线程, 做读操作, 三个线程阻塞    ...

delphi 线程教学第二节:在线程时空中操作界面(UI)

第二节:在线程时空中操作界面(UI) 1.为什么要用 TThread ? TThread 基于操作系统的线程函数封装,隐藏了诸多繁琐的细节。 适合于大部分情况多线程任务的实现。这个理由足够了吧? 什么?你要用 windows 的线程 api 来实现多线程? 我可以负责任地告诉你,如果你用 api 来实现多线程任务, 加之你天资聪明,对 delphi...

解决mySQL占用内存超大问题

为了装mysql环境测试,装上后发现启动后mysql占用了很大的虚拟内存,达8百多兆。网上搜索了一下,得到高人指点my.ini。再也没见再详细的了..只好打开my.ini逐行的啃,虽然英文差了点,不过多少M还是看得明的^-^ 更改后如下: innodb_buffer_pool_size=576M ->256M InnoDB引擎缓冲区占了大头,首要就是...

Java多线程-线程的调度(合并)

线程的合并的含义就是将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时可以使用join方法。 join为非静态方法,定义如下:void join(): 等待该线程终止。void join(long millis): 等待该线程终止的时间最长为 millis 毫秒。void join(long millis,...