C#报错"线程间操作无效: 从不是创建控件“XXX”的线程访问它"--解决示例

简介:

C# Winform程序中,使用线程对界面进行更新需要特殊处理,否则会出现异常“线程间操作无效: 从不是创建控件“taskView”的线程访问它。”

在网文“http://www.cnblogs.com/smileberry/p/3912918.html”的知道下,我做了下面的例程,希望对大家有所帮助,如果注释不够的话请访问原文。

例程是点击按钮后启动线程更新一个标签的文字,界面如下:

 

程序如下:

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadCgGui
{
    public partial class Form1 : Form
    {
        // 定义委托类型
        delegate void SetTextCallback(String str);

        public Form1()
        {
            InitializeComponent();
        }

        // 点击按钮启动线程
        private void button1_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(threadProcSafe);
            th.Start();
        }

        // 线程主体方法
        private void threadProcSafe()
        {
            for (int i = 0; i < 1000; i++)
            {
                if (i % 2 == 0)
                {
                    this.setText("123456789");
                }
                else
                {
                    this.setText("一二三四五六七八九");
                }

                Thread.Sleep(1000);
            }
            
        }

        // 本方法是跨线程更新UI使用的主流方法,使用控件的Invoke/BeginInvoke方法,将委托转到UI线程上调用,实现线程安全的更新
        // 本质上还是把线程中要提交的消息,通过控制句柄调用委托交到UI线程中处理
        public void setText(String str)
        {
            if (label1.InvokeRequired)
            {
                // 解决窗体关闭时出现“访问已释放句柄”异常
                while (label1.IsHandleCreated == false)
                {
                    if (label1.Disposing || label1.IsDisposed) return;
                }

                SetTextCallback d = new SetTextCallback(setText);
                label1.Invoke(d, new object[] { str });

            }
            else
            {
                label1.Text = str;
            }
           
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // 彻底的退出
            System.Environment.Exit(0);
        }
    }

}
复制代码

 

例程下载:

 http://files.cnblogs.com/files/xiandedanteng/ThreadCgGui20170626.zip










本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/xiandedanteng/p/7084642.html,如需转载请自行联系原作者


相关文章
|
1月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
1月前
|
安全 编译器 C#
C#学习相关系列之多线程---lock线程锁的用法
C#学习相关系列之多线程---lock线程锁的用法
|
1月前
|
C#
C#学习相关系列之多线程---ConfigureAwait的用法
C#学习相关系列之多线程---ConfigureAwait的用法
|
1月前
|
C#
C#学习相关系列之多线程---TaskCompletionSource用法(八)
C#学习相关系列之多线程---TaskCompletionSource用法(八)
|
1月前
|
Java C#
C#学习系列相关之多线程(五)----线程池ThreadPool用法
C#学习系列相关之多线程(五)----线程池ThreadPool用法
|
30天前
|
算法 安全 Unix
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
29 0
|
1月前
|
C#
C#学习系列相关之多线程(二)----Thread类介绍
C#学习系列相关之多线程(二)----Thread类介绍
|
1月前
|
Java C#
C#学习相关系列之多线程(七)---Task的相关属性用法
C#学习相关系列之多线程(七)---Task的相关属性用法
|
1月前
|
Java C#
C#学习相关系列之多线程(六)----Task的初级使用
C#学习相关系列之多线程(六)----Task的初级使用
|
1月前
|
C#
C#学习系列相关之多线程(四)----async和await的用法
C#学习系列相关之多线程(四)----async和await的用法