某个线程上创建的控件不能成为在另一个线程上创建的控件的父级(转)

转载 2006年06月23日 08:46:00
解决多线程操作控件时可能出现的异常:“在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级”
Posted on 2005-10-25 14:47 HQT 阅读(218) 评论(0)  编辑 收藏 收藏至365Key 所属分类: .NET
.NET Framework 中关于“多线程 Windows 窗体控件示例”的一些摘要:

------------------------------------------------------

“Windows 窗体”使用单线程单元 (STA) 模型,因为“Windows 窗体”基于本机 Win32 窗口,而 Win32 窗口从本质上而言是单元线程。STA 模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。除了 Windows 窗体之外,.NET Framework 中的类使用自由线程模型。有关 .NET Framework 中的线程的信息,请参见线程处理

STA 模型要求需从控件的非创建线程调用的控件上的任何方法必须被封送到(在其上执行)该控件的创建线程。基类 Control 为此目的提供了若干方法(InvokeBeginInvokeEndInvoke)。Invoke 生成同步方法调用;BeginInvoke 生成异步方法调用。

如果您在控件中为大量占用资源的任务使用多线程,则用户界面可以在背景线程上执行一个大量占用资源的计算的同时保持可响应。

------------------------------------------------------

下面直接给出我的实例程序,一个按钮是非创建线程直接调用 DataGrid 控件的数据绑定,将抛出异常;
另一个按钮是通过 Invoke 调用,将成功执行。

using System;
using System.Data;
using System.Threading;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace MultiThreadOperateControls
{
    
/// <summary>
    
/// Form1 的摘要说明。
    
/// </summary>

    public class Form1 : System.Windows.Forms.Form
    
{
        
        
private delegate void BindDataGridDelegate();        // 创建委托和委托对象
        private BindDataGridDelegate bindDataGridDelegate;

        Thread bindGridThread;

        
private System.Windows.Forms.Button btnErrorHandle;
        
private System.Windows.Forms.Button btnSuccessHandle;
        
private System.Windows.Forms.DataGrid dataGrid1;
        
/// <summary>
        
/// 必需的设计器变量。
        
/// </summary>

        private System.ComponentModel.Container components = null;

        
public Form1()
        
{
            bindDataGridDelegate 
= new BindDataGridDelegate(BindDataGrid);    // 实例化委托对象并指定调用的方法

            
//
            
// Windows 窗体设计器支持所必需的
            
//
            InitializeComponent();

            
//
            
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
            
//
        }


        
/// <summary>
        
/// 清理所有正在使用的资源。
        
/// </summary>

        protected override void Dispose( bool disposing )
        
{
            
if( disposing )
            
{
                
if (components != null
                
{
                    components.Dispose();
                }

            }

            
base.Dispose( disposing );
        }


        
Windows 窗体设计器生成的代码

        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>

        [STAThread]
        
static void Main() 
        
{
            Application.Run(
new Form1());
        }


        
private void Form1_Load(object sender, System.EventArgs e)
        
{
            BindDataGrid();
        }


        
private void btnErrorHandle_Click(object sender, System.EventArgs e)
        
{
            StopBindThread();
            bindGridThread 
= new Thread(new ThreadStart(BindDataGrid));    // 直接调用非此线程创建的控件的操作 抛出异常
            bindGridThread.Start();        
        }

        
private void btnSuccessHandle_Click(object sender, System.EventArgs e)
        
{            
            StopBindThread();
            bindGridThread 
= new Thread(new ThreadStart(InvokeBindDataGrid)); // 通过委托调用,合法
            bindGridThread.Start();                
        }


        
private void BindDataGrid()
        
{
            
int dataGridItemLenght = 5;
            DataTable dt 
= new DataTable("DataGridSource");
            dt.Columns.Add(
"RandomValue");
            
for(int i=0;i<dataGridItemLenght;i++)
            
{
                Random r 
= new Random();
                DataRow dr 
= dt.NewRow();
                dr[
0= r.Next(1,500);
                dt.Rows.Add(dr);
            }


            
try
            
{
                dataGrid1.DataSource 
= dt;
            }

            
catch(Exception ex)
            
{
                MessageBox.Show(ex.Message);
            }

        }

        
        
private void InvokeBindDataGrid()        // 调用非此线程创建的控件的操作必须用 Invoke 或 BeginInvoke .否则将抛出异常
        {        
            dataGrid1.Invoke(bindDataGridDelegate,
null);            
        }

        
private void StopBindThread()
        
{
            
if((bindGridThread != null)&&(bindGridThread.IsAlive))
            
{
                bindGridThread.Abort();
                bindGridThread.Join();
            }

            bindGridThread 
= null;
        }

    }

}

举报

相关文章推荐

WinForm中新开一个线程操作窗体上的控件(跨线程操作控件)GOOD

最近在做一个winform的小软件(抢票的...)。登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是创建控件“...
  • Baple
  • Baple
  • 2014-05-08 23:11
  • 1930

如何在基于 MFC 的 ActiveX 控件激发事件,在 Visual c + + 中的启动另一个线程

http://support.microsoft.com/kb/q157437/ 查看本文应用于的产品 注意Microsoft Visual c + + 2008年、 Microsof...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

多线程委托之跨线程问题分析--在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke(解决方法已更新)

多线程委托之跨线程问题分析 今天在写一个程序测试运行跨线程同步的时候出一个异常信息。 异常信息:System.InvalidOperationException “在创建窗口句柄之前,不能在控件上调...

线程间操作无效: 从不是创建控件的线程访问它的三种解决方法

今天遇到这个问题,百度了下,把解决的方法总结出来。 我们在ui线程创建的子线程操作ui控件时,系统提示错误详细信息为: 线程间操作无效: 从不是创建控件“XXX”的线程访问它。   就我知道的有三...
  • jumtre
  • jumtre
  • 2015-04-07 22:59
  • 14797

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

摘自:http://blog.csdn.net/hongkaihua1987/article/details/7439231            http://hi.baidu.com/jcser...

C# 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~

线程间操作无效: 从不是创建控件“”的线程访问它。 听说2003里边不会,我不知道是不是这样的,反正一直都在用05~ 05里会出这个问题的,貌似是为了安全~ 哦,现在知道的解决方法有两个~ ...

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

访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安...

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

这个错误提示导致我花了一天半的时间来思考为什么会有这个问题.. 以前只明白线程的作用和意义...但是在用的时候却没怎么考虑过..只知道用... 我这个项目是winform的,需要用到webserv...
  • phker
  • phker
  • 2012-05-18 12:51
  • 2188

C#线程间操作无效: 从不是创建控件" XX" 的线程访问它

转自:http://www.arasplm.net/index.php/zh/community/myblog/c-xx-.html 前些天做的要使用到线程的项目,现在和大家分享一下感受! ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)