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

转载 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 为此目的提供了若干方法(Invoke、BeginInvoke 和 EndInvoke)。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;
        }

    }

}

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

解决多线程操作控件时可能出现的异常:“在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级” Posted on 2005-10-25 14:47 HQT 阅读(340) 评论(2)  编辑 ...
  • czsd82
  • czsd82
  • 2006年09月13日 17:38
  • 4531

解决 在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级

public partial class Form1 : Form { public Form1() { InitializeCompo...
  • CLeopard
  • CLeopard
  • 2014年02月27日 13:54
  • 6699

决多线程操作控件时可能出现的异常:“在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级”

.NET Framework 中关于“多线程 Windows 窗体控件示例”的一些摘要:------------------------------------------------------“W...
  • fsc2988877
  • fsc2988877
  • 2007年07月07日 16:01
  • 1436

[vb.net]解决 "在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级"

在一段给DATAGRID控件绑定DATATABLE对象的代码中, 加入线程的操作后提示"在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级"   在CSDN的论坛中找到其他人的建议"使...
  • astromercy
  • astromercy
  • 2008年09月19日 16:20
  • 1348

解决 Control.Invoke 必须用于与在独立线程上创建的控件交互。在智能设备上的(c# / PDA)

using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; ...
  • li0531
  • li0531
  • 2012年06月18日 17:39
  • 2754

在WM下,获得当前路径处理和解决异常“Control.Invoke 必须用于与在独立线程上创建的控件交互。”

Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly.GetName.CodeBase)Control.Invok...
  • ansencumt
  • ansencumt
  • 2010年11月21日 12:18
  • 4152

c# 解决 Control.Invoke 必须用于与在独立线程上创建的控件交互。在智能设备上的(PDA)

最近搞的 一个程序, 要用到 线程 操作,但是 在线程调用的 方法中 有控件的参与。所以 在调用的时候   出现了这样的  错误  “Control.Invoke 必须用于与在独立线程上创建的控件交...
  • linghao00
  • linghao00
  • 2013年05月19日 17:15
  • 2404

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

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

错误:在一个线程上创建的控件不能成为在另一个线程控件的父级(处理方法)

using System;using System.Data;using System.Threading;using System.Drawing;using System.Collections;...
  • shootero
  • shootero
  • 2006年01月04日 23:29
  • 1226

C#c# 从不是创建控件 的线程访问它。

有两种方式解决  1.在窗体构造函数中写Control.CheckForIllegalCrossThreadCalls =false; 2.使用Invoke等委托函数。 问题原因是。ne...
  • fengda2870
  • fengda2870
  • 2016年06月01日 10:21
  • 3796
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:某个线程上创建的控件不能成为在另一个线程上创建的控件的父级(转)
举报原因:
原因补充:

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