解决线程不能访问用户界面组件的问题
//因在项目的窗体文本框中要显示COM组件回调函数所传回来的值,
//谁知测试时竟然显示
//""System.InvalidOperationException: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。"
//或者干脆罢工,一个也不给你显示出来.让我大为恼火,毕竟"魔高一尺,道高一丈".于是对此做了些分析与测试.
//终于顺利解决.
//究其原因为: 在Windows From里面,需要在线程里面访问界面元素,需要使用BeginInvoke来完成.
//本示例通过调用cAdd类中的 GetAddResult() 方法,通过事件(AddComplete)实时触发传送计算结果 ,
//在窗体的richTextBox中显示出来.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TestInteractiveThread
{
public delegate void AddHandler(int iResult);
public partial class Form1 : Form
{
private cAdd ca;
public Form1()
{
InitializeComponent();
ca = new cAdd();
ca.AddComplete += new AddHandler(ca_AddComplete);
}
public delegate void InvokeInitDelegate(); //不带参数的委托
public delegate void MyInitDelegate(RichTextBox myRtb, string strTemp); //带参数的异步委托
void ca_AddComplete(int iResult)
{
try
{
// this.richTextBox1.AppendText(Environment.NewLine + iResult.ToString());
//采用上面的方法将产生下面的错误.
//"System.InvalidOperationException: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。"
//在Windows From里面,需要在线程里面访问界面元素,需要使用BeginInvoke来完成.
//将上面的代码屏蔽掉,采用
//在创建控件的基础句柄所在线程上,用指定的参数异步执行指定委托。
this.richTextBox1.BeginInvoke(new MyInitDelegate(DelegateInitMethod), new object[] { this.richTextBox1, iResult.ToString() });
}
catch (System.Exception err)
{
strErr = err.ToString();
//在创建控件的基础句柄所在线程上异步执行委托。在创建控件的基础句柄所在线程上异步执行指定委托。
//由 .NET Compact Framework 支持。
this.BeginInvoke(new InvokeInitDelegate(InvokeInitMethod));
MessageBox.Show(err.ToString());
//throw new Exception("The method or operation is not implemented.");
}
}
private static string strErr = "";
private void InvokeInitMethod()
{
this.richTextBox1.AppendText(strErr);
}
public void DelegateInitMethod(RichTextBox myRtb, string strTemp)
{
myRtb.AppendText(System.Environment.NewLine + strTemp);
}
private void button_Test_Click(object sender, EventArgs e)
{
//ca.GetAddResult();
//为了说明此问题我们采用下面的线程方法来调用.此时系统将弹出
//"System.InvalidOperationException: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。"
System.Threading.Thread myThread = new System.Threading.Thread(
new System.Threading.ThreadStart(ca.GetAddResult));
myThread.Start();
}
private void button1_Click(object sender, EventArgs e)
{
this.richTextBox1.AppendText ( ca.AddInterlink(10).ToString() );
}
}
public class cAdd
{
public event AddHandler AddComplete;
public void GetAddResult()
{
int iResult=AddInterlink2(11);
AddComplete(iResult);
}
//1+1+2+3+5+8+13+21..+n
private static int AddInterlink2(int i)
{
int[] x = new int[i+1];
x[0] = 1;
x[1] = 1;
for (int j = 2; j <= i; j++)
{
x[j] = x[j - 1] + x[j - 2];
}
return x[i];
}
//也可采用下面的方法
private int x1=1,x2 = 1;
//1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + + n
//x1,x2, x1, x2, x1, x2, x1, x2,.
//x1,x2, x3, x1, x2, x3, .
public StringBuilder AddInterlink(int i)
{
StringBuilder s1 = new StringBuilder();
s1.Append(x1.ToString() +","+ x2.ToString()+","); ;
int j=2;
while (j < i)
{
x1 += x2;
x2 += x1;
s1.Append(x1.ToString() +","+ x2.ToString()+",");
j+=2;
}
return s1;
}
}
}
//谁知测试时竟然显示
//""System.InvalidOperationException: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。"
//或者干脆罢工,一个也不给你显示出来.让我大为恼火,毕竟"魔高一尺,道高一丈".于是对此做了些分析与测试.
//终于顺利解决.
//究其原因为: 在Windows From里面,需要在线程里面访问界面元素,需要使用BeginInvoke来完成.
//本示例通过调用cAdd类中的 GetAddResult() 方法,通过事件(AddComplete)实时触发传送计算结果 ,
//在窗体的richTextBox中显示出来.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TestInteractiveThread
{
public delegate void AddHandler(int iResult);
public partial class Form1 : Form
{
private cAdd ca;
public Form1()
{
InitializeComponent();
ca = new cAdd();
ca.AddComplete += new AddHandler(ca_AddComplete);
}
public delegate void InvokeInitDelegate(); //不带参数的委托
public delegate void MyInitDelegate(RichTextBox myRtb, string strTemp); //带参数的异步委托
void ca_AddComplete(int iResult)
{
try
{
// this.richTextBox1.AppendText(Environment.NewLine + iResult.ToString());
//采用上面的方法将产生下面的错误.
//"System.InvalidOperationException: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。"
//在Windows From里面,需要在线程里面访问界面元素,需要使用BeginInvoke来完成.
//将上面的代码屏蔽掉,采用
//在创建控件的基础句柄所在线程上,用指定的参数异步执行指定委托。
this.richTextBox1.BeginInvoke(new MyInitDelegate(DelegateInitMethod), new object[] { this.richTextBox1, iResult.ToString() });
}
catch (System.Exception err)
{
strErr = err.ToString();
//在创建控件的基础句柄所在线程上异步执行委托。在创建控件的基础句柄所在线程上异步执行指定委托。
//由 .NET Compact Framework 支持。
this.BeginInvoke(new InvokeInitDelegate(InvokeInitMethod));
MessageBox.Show(err.ToString());
//throw new Exception("The method or operation is not implemented.");
}
}
private static string strErr = "";
private void InvokeInitMethod()
{
this.richTextBox1.AppendText(strErr);
}
public void DelegateInitMethod(RichTextBox myRtb, string strTemp)
{
myRtb.AppendText(System.Environment.NewLine + strTemp);
}
private void button_Test_Click(object sender, EventArgs e)
{
//ca.GetAddResult();
//为了说明此问题我们采用下面的线程方法来调用.此时系统将弹出
//"System.InvalidOperationException: 线程间操作无效: 从不是创建控件“richTextBox1”的线程访问它。"
System.Threading.Thread myThread = new System.Threading.Thread(
new System.Threading.ThreadStart(ca.GetAddResult));
myThread.Start();
}
private void button1_Click(object sender, EventArgs e)
{
this.richTextBox1.AppendText ( ca.AddInterlink(10).ToString() );
}
}
public class cAdd
{
public event AddHandler AddComplete;
public void GetAddResult()
{
int iResult=AddInterlink2(11);
AddComplete(iResult);
}
//1+1+2+3+5+8+13+21..+n
private static int AddInterlink2(int i)
{
int[] x = new int[i+1];
x[0] = 1;
x[1] = 1;
for (int j = 2; j <= i; j++)
{
x[j] = x[j - 1] + x[j - 2];
}
return x[i];
}
//也可采用下面的方法
private int x1=1,x2 = 1;
//1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + + n
//x1,x2, x1, x2, x1, x2, x1, x2,.
//x1,x2, x3, x1, x2, x3, .
public StringBuilder AddInterlink(int i)
{
StringBuilder s1 = new StringBuilder();
s1.Append(x1.ToString() +","+ x2.ToString()+","); ;
int j=2;
while (j < i)
{
x1 += x2;
x2 += x1;
s1.Append(x1.ToString() +","+ x2.ToString()+",");
j+=2;
}
return s1;
}
}
}