`
coolerbaosi
  • 浏览: 727205 次
文章分类
社区版块
存档分类
最新评论

多线程程序中线程安全的可视化操纵控件

 
阅读更多

在我们写WinForm程序的时候,如果在新创建的另外一个线程中直接操纵界面的可视化控件,会提示错误。如下提示:

线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。

代码如下所示,当没有从线程中操作可视化控件的时候,代码是安全的。

namespace SafeThread
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Text += "add message through main thread!\n";
        }

        //private void button1_Click(object sender, EventArgs e)
        //{
        //    Thread thread = new Thread(new ThreadStart(addMsg));
        //    thread.IsBackground = true;
        //    thread.Start();
        //}

        //private void addMsg()
        //{
        //    this.richTextBox1.Text += "add message through other thread!\n";
        //}
    }
}


但是当另外一个按钮从其他的线程直接操作可视化控件以后,就会提示错误的操作:代码如下:

namespace SafeThread
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Text += "add message through main thread!\n";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(addMsg));
            thread.IsBackground = true;
            thread.Start();
        }

        private void addMsg()
        {
            this.richTextBox1.Text += "add message through other thread!\n";
        }
    }
}


这其中的原因,在于windows窗体编程的消息机制,windows维持一个给窗体传递的消息列表,记录每个事件消息发送给了每个可视化控件,系统单独的为消息列表维护了一个线程,并且这个消息列表属于队列,先进先出。如果从自己添加的线程中给可视化控件传递消息,则会打乱系统的消息列表,所以是系统不允许的。但是我们又需要在多线程中操作可视化控件,怎么办呢?可以用委托和反射来实现。

实现的代码并不复杂,只要对每个可视化控件的操作添加一个委托就可以了。

一种实现的代码如下所示:

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 SafeThread
{
    public partial class Form1 : Form
    {
        private delegate void callRichTextBox(string s);

        public Form1()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Text += "add message through main thread!\n";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ParameterizedThreadStart(addMsg));
            thread.IsBackground = true;
            thread.Start("add message through other thread!");
        }


        private void addMsg(object log)
        {
            if (richTextBox1.InvokeRequired)
            {
                callRichTextBox call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
                // 下面调用的Invoke()函数,如果委托有参数,则第二个参数则为委托的参数
                this.richTextBox1.Invoke(call, log);
            }
            else
            {
                this.richTextBox1.Text += "add message through other thread!\n";
            }
        }
    }
}


测试表明,程序运行正常。

上面使用了显示定义的委托,也可以通过下面这种方法来定义委托,这里使用了C# 系统已经定义好的一种委托Action<>:

namespace SafeThread
{
    public partial class Form1 : Form
    {
        //private delegate void callRichTextBox(string s);

        public Form1()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Text += "add message through main thread!\n";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ParameterizedThreadStart(addMsg));
            thread.IsBackground = true;
            thread.Start("add message through other thread!");
        }


        private void addMsg(object log)
        {
            if (richTextBox1.InvokeRequired)
            {
                //callRichTextBox call = delegate(string s) { this.richTextBox1.Text += s + "\n"; };
                Action<string> call = delegate(string t) { this.richTextBox1.Text += t + "\n"; };
                // 下面调用的Invoke()函数,如果委托有参数,则第二个参数则为委托的参数
                this.richTextBox1.Invoke(call, log);
            }
            else
            {
                this.richTextBox1.Text += "add message through other thread!\n";
            }
        }
    }
}


同样程序运行正常,这里比较简单,所以就不给出用户界面截图了。

分享到:
评论

相关推荐

    VC++可视化编程指南

    第一课 Windows编程和面向对象技术  1.1 Windows发展历史 ...第十二章 多线程与串行通信  12.1 多任务、进程和线程  12.2 线程的同步  12.3 串行通信与重叠I/O  12.4 一个通信演示程序  12.5 小结

    QRMaker.ocx控件

    不可多得的二维码ActiveX控件,适用于VC++、VB、Delphi等可视化应用程序。包含使用说明和控件属性介绍。 一、运行regsvr32 QRMAKER.OCX 二、VB部件添加 QRMAKER.OCX 三、窗口添加一QRMAKER.OCX With QRmaker1 ....

    Hanoi塔 可视化程序源码(C#)

    最近学了一段时间C#,花了几天写的程序,用了多线程,GDI+,用户自定义控件,大家可以相互学习,有问题可以回复我,我的邮箱是gurongfang@gmail.com

    基于c++的图书馆图书管理系统

    以MFC框架开发技术使用C++ 做为编程语言、SQLServer2008做为数据库。设计了以类封装为基础的图书馆管理系统...文本编辑控件richedit使用、MFC基础高版本控件使用、多线程设计、窗体资源文件可视化设计等细节开发技术。

    基于CTP和Qt的可视化期货监控系统.zip

    Qt Designer是一个可视化界面设计工具,允许通过拖放操作构建UI,所见即所得。 非GUI应用开发: 除了GUI程序,Qt同样适用于开发命令行工具、后台服务、嵌入式系统等非图形化应用。其底层API涵盖了文件处理、线程...

    条码识别图书检索系统

    以MFC框架开发技术使用C++ 做为编程语言、SQLServer2012做为数据库...文本编辑控件richedit使用、MFC基础高版本控件使用、多线程设计、窗体资源文件可视化设计等细节开发技术。系统具有易用性、通用性和良好的流畅性。

    Visual C++ 6.0程序设计从入门到精通

    本书分为基础篇和案例篇两篇,基础篇从Visual C++集成开发环境讲起,介绍了MFC与应用程序框架、C++语言基础与工具控件、多媒体技术、多线程编程、网络编程等技术;案例篇中通过两个开发实例介绍了基础知识的运用技巧...

    VC++ 编程指南_中文chm

    第一课 Windows编程和面向对象技术  1.1 Windows发展历史 ...第十二章 多线程与串行通信  12.1 多任务、进程和线程  12.2 线程的同步  12.3 串行通信与重叠I/O  12.4 一个通信演示程序  12.5 小结

    VC++编程指南(中文版).chm

    VC++编程指南(中文版),不错的一本电子书。啥也不说了,直接看内容预览...第十二章 多线程与串行通信  12.1 多任务、进程和线程  12.2 线程的同步  12.3 串行通信与重叠I/O  12.4 一个通信演示程序  12.5 小结

    《Delphi7编程100例》代码

    ToolBar工具栏控件的使用动态建立主菜单选项窗口界面的动态分隔条动态设置...程序使用DrawGrid控件制作五子棋多彩的数据报表按压缩比将BMP转换为JPG16位真彩转换到256色调整图片的RGB对比度实现图像的灰度级处理效果3种...

    数据可视化智能软件主要性能指标.doc

    数据可视化智能软件主要性能指标 1) 分布式实时数据库 A 软件应采用多线程的处理机制,分布式组件的设计支持负载均衡体系。 B 内置动态优化功能,可保证用户在访问一个窗口、鼠标动作等所产生的数据交互的快速 响应...

    Visual.Basic.NET程序设计案例教程

    第6章 VB.NET的可视化组件 第7章 VB.NET的界面设计 第8章 VB.NET数据库访问技术 第9章 文件处理 第10章 VB.NET多线程机制 第11章 使用ASP.NET开发Web窗体技术 第12章 VB.NET程序案例应用 参考文献

    Visual_C++从入门到实践

    其中,可视化编程详细讲解了对话框、单文档和多文档、Windows标准控件、菜单、工具栏和状态栏设计、图形处理和输入输出等内容。Windows编程则详细讲解了文件操作、注册表和INI文件、DLL、多线程编程。开发和实例篇...

    C#实训教程

    13.2 多线程应用程序 275 13.3 线程的处理 276 13.4 线程的优先级 282 13.5 同步 283 13.6 同步问题 285 13.7 内容总结 288 14 Winform基本概念 289 14.1 .NET Windows应用程序开发 289 14.2 .NET框架类库...

    Delphi 程序设计基础教程

    对话框、工具栏和状态栏设计、Delphi 多媒体应用、Delphi 异常处理与调试、数据库编程、报表与图表、 面向对象的程序设计、Delphi 自定义组件的开发、动态链接库(DLLs)编程、多线程、文件操作内容。每章 后面都提供...

    WPF编程宝典 part1

    14.1.2 在元素中封装可视化对象 329 14.1.3 命中测试 332 14.1.4 复杂的命中测试 334 14.2 效果 338 14.2.1 BlurEffect类 338 14.2.2 DropShadowEffect类 339 14.2.3 ShaderEffect类 340 14.3 WriteableBitmap类 342...

    Delphi7编程100例

    可视化的Ping工具 使用IdMappedPortTCP进行端口映射 动态设置ODBC数据源 用ADO控件打开Access数据库 DBGrid中的记录到Html页面的转换 在DBGrid中实现任意方向查找 在DBGrid中通过动态下拉列表查找记录 ...

    Delphi编程100例

    可视化的Ping工具 使用IdMappedPortTCP进行端口映射 动态设置ODBC数据源 用ADO控件打开Access数据库 DBGrid中的记录到Html页面的转换 在DBGrid中实现任意方向查找 在DBGrid中通过动态下拉列表查找记录 用DBGrid组件...

    xise寄生虫破解版

    可视化操作,支持PHP、ASP、ASPX、JSP语言环境 多线程线程池操作,API编写,字节集读取,winhttpAPI访问,真正达到毫秒级反应 更适合新手使用,不仅有可视界面,并带有一键返回网站根目录,让你完全掌握自身方位 ...

    Visual.Basic.2010.&.NET4.高级编程(第6版)-文字版.pdf

    14.2.9 可视化继承 549 14.2.10 滚动窗体 549 14.2.11 mdi窗体 549 14.2.12 vb 2010中的mdi样例 550 14.2.13 对话框窗体 551 14.2.14 运行时的窗体 553 14.2.15 默认的窗体实例 554 14.3 控件 554 ...

Global site tag (gtag.js) - Google Analytics