zoukankan      html  css  js  c++  java
  • C# 线程thread

    一、问题总结

     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

  • 相关阅读:
    HDU 1269 迷宫城堡
    HDU 4771 Stealing Harry Potter's Precious
    HDU 4772 Zhuge Liang's Password
    HDU 1690 Bus System
    HDU 2112 HDU Today
    HDU 1385 Minimum Transport Cost
    HDU 1596 find the safest road
    HDU 2680 Choose the best route
    HDU 2066 一个人的旅行
    AssetBundle管理机制(下)
  • 原文地址:https://www.cnblogs.com/ike_li/p/11327575.html
Copyright © 2011-2022 走看看