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

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

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

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

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

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

None.gif using  System;
None.gif
using  System.Data;
None.gif
using  System.Threading;
None.gif
using  System.Drawing;
None.gif
using  System.Collections;
None.gif
using  System.ComponentModel;
None.gif
using  System.Windows.Forms;
None.gif
None.gif
namespace  MultiThreadOperateControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Form1 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class Form1 : System.Windows.Forms.Form
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
InBlock.gif        
private delegate void BindDataGridDelegate();        // 创建委托和委托对象
InBlock.gif
        private BindDataGridDelegate bindDataGridDelegate;
InBlock.gif
InBlock.gif        Thread bindGridThread;
InBlock.gif
InBlock.gif        
private System.Windows.Forms.Button btnErrorHandle;
InBlock.gif        
private System.Windows.Forms.Button btnSuccessHandle;
InBlock.gif        
private System.Windows.Forms.DataGrid dataGrid1;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 必需的设计器变量。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private System.ComponentModel.Container components = null;
InBlock.gif
InBlock.gif        
public Form1()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            bindDataGridDelegate 
= new BindDataGridDelegate(BindDataGrid);    // 实例化委托对象并指定调用的方法
InBlock.gif
InBlock.gif            
//
InBlock.gif            
// Windows 窗体设计器支持所必需的
InBlock.gif            
//
InBlock.gif
            InitializeComponent();
InBlock.gif
InBlock.gif            
//
InBlock.gif            
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 清理所有正在使用的资源。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        protected override void Dispose( bool disposing )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if( disposing )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (components != null
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    components.Dispose();
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
base.Dispose( disposing );
ExpandedSubBlockEnd.gif        }

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
Windows 窗体设计器生成的代码#region Windows 窗体设计器生成的代码
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
InBlock.gif        
/// 此方法的内容。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private void InitializeComponent()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.btnErrorHandle = new System.Windows.Forms.Button();
InBlock.gif            
this.btnSuccessHandle = new System.Windows.Forms.Button();
InBlock.gif            
this.dataGrid1 = new System.Windows.Forms.DataGrid();
InBlock.gif            ((System.ComponentModel.ISupportInitialize)(
this.dataGrid1)).BeginInit();
InBlock.gif            
this.SuspendLayout();
InBlock.gif            
// 
InBlock.gif            
// btnErrorHandle
InBlock.gif            
// 
InBlock.gif
            this.btnErrorHandle.Location = new System.Drawing.Point(4024);
InBlock.gif            
this.btnErrorHandle.Name = "btnErrorHandle";
InBlock.gif            
this.btnErrorHandle.Size = new System.Drawing.Size(11240);
InBlock.gif            
this.btnErrorHandle.TabIndex = 0;
InBlock.gif            
this.btnErrorHandle.Text = "ErrorHandle";
InBlock.gif            
this.btnErrorHandle.Click += new System.EventHandler(this.btnErrorHandle_Click);
InBlock.gif            
// 
InBlock.gif            
// btnSuccessHandle
InBlock.gif            
// 
InBlock.gif
            this.btnSuccessHandle.Location = new System.Drawing.Point(23224);
InBlock.gif            
this.btnSuccessHandle.Name = "btnSuccessHandle";
InBlock.gif            
this.btnSuccessHandle.Size = new System.Drawing.Size(11240);
InBlock.gif            
this.btnSuccessHandle.TabIndex = 1;
InBlock.gif            
this.btnSuccessHandle.Text = "SuccessHandle";
InBlock.gif            
this.btnSuccessHandle.Click += new System.EventHandler(this.btnSuccessHandle_Click);
InBlock.gif            
// 
InBlock.gif            
// dataGrid1
InBlock.gif            
// 
InBlock.gif
            this.dataGrid1.DataMember = "";
InBlock.gif            
this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
InBlock.gif            
this.dataGrid1.Location = new System.Drawing.Point(3288);
InBlock.gif            
this.dataGrid1.Name = "dataGrid1";
InBlock.gif            
this.dataGrid1.Size = new System.Drawing.Size(336176);
InBlock.gif            
this.dataGrid1.TabIndex = 2;
InBlock.gif            
// 
InBlock.gif            
// Form1
InBlock.gif            
// 
InBlock.gif
            this.AutoScaleBaseSize = new System.Drawing.Size(614);
InBlock.gif            
this.ClientSize = new System.Drawing.Size(408301);
InBlock.gif            
this.Controls.Add(this.dataGrid1);
InBlock.gif            
this.Controls.Add(this.btnSuccessHandle);
InBlock.gif            
this.Controls.Add(this.btnErrorHandle);
InBlock.gif            
this.Name = "Form1";
InBlock.gif            
this.Text = "多线程窗体控件处理事例";
InBlock.gif            
this.Load += new System.EventHandler(this.Form1_Load);
InBlock.gif            ((System.ComponentModel.ISupportInitialize)(
this.dataGrid1)).EndInit();
InBlock.gif            
this.ResumeLayout(false);
InBlock.gif
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 应用程序的主入口点。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        [STAThread]
InBlock.gif        
static void Main() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Application.Run(
new Form1());
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void Form1_Load(object sender, System.EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            BindDataGrid();
ExpandedSubBlockEnd.gif        }

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

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

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

InBlock.gif
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                dataGrid1.DataSource 
= dt;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch(Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                MessageBox.Show(ex.Message);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

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

InBlock.gif        
private void StopBindThread()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if((bindGridThread != null)&&(bindGridThread.IsAlive))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                bindGridThread.Abort();
InBlock.gif                bindGridThread.Join();
ExpandedSubBlockEnd.gif            }

InBlock.gif            bindGridThread 
= null;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值