从另一个线程在表单上添加控件
Posted
技术标签:
【中文标题】从另一个线程在表单上添加控件【英文标题】:Add a control on a form, from another Thread 【发布时间】:2011-01-16 02:00:28 【问题描述】:我试图推迟向我的主窗体添加控件,目的是加快它的开始时间。好吧,我在以下异常中运行:
跨线程操作无效: 从线程访问的控件“Form1” 除了它创建的线程 开。
我试图在一个较小的示例上简单地解决问题,但问题仍然存在。这是我的代码:
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace AddConrolFromAnotherThread
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void AddButton()
if(this.InvokeRequired)
this.Invoke(new MethodInvoker(this.AddButton));
Random random = new Random(2);
Thread.Sleep(20);
Button button = new Button();
button.Size = new Size(50,50);
button.Location =
new Point(random.Next(this.Width),random.Next(this.Height));
this.Controls.Add(button);
private void buttonStart_Click(object sender, EventArgs e)
Thread addControlThread =
new Thread(new ThreadStart(this.AddButton));
addControlThread.Start();
我确实使用了 Invoke 方法并检查了 InvokeRequiered 是否为真,但 InvokeRequiered 一直保持“真”。我真的不明白这一点。至少我会期待 *** 异常,因为这是一个递归调用。
那么,如果有人遇到类似的问题,请你告诉我我做错了什么?
【问题讨论】:
【参考方案1】:您的代码中的问题是您添加了两个按钮。
将代码放在 if 块之后的 else 块中。
private void AddButton()
if(this.InvokeRequired)
this.Invoke(new MethodInvoker(this.AddButton));
else
Random random = new Random(2);
Thread.Sleep(20);
Button button = new Button();
button.Size = new Size(50,50);
button.Location = new Point(random.Next(this.Width),random.Next(this.Height));
this.Controls.Add(button);
【讨论】:
【参考方案2】:你可以这样做......
private void AddButton()
if(this.InvokeRequired)
Invoke((MethodInvoker)delegate ()
Random random = new Random(2);
Thread.Sleep(20);
Button button = new Button();
button.Size = new Size(50,50);
button.Location = new
Point(random.Next(this.Width),random.Next(this.Height));
this.Controls.Add(button);
);
【讨论】:
【参考方案3】:改用匿名方法。说明如下。
如果我们有这样的形式:
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void Form1_Load(object sender, EventArgs e)
Thread t = new Thread(new ThreadStart(Start));
t.Start();
private void UpdateText()
button1.Text = "New Text";
void Start()
UpdateText();
这将引发异常。
将 UpdateText 更改为:
private delegate void MyDelegate();
private void UpdateText()
if (button1.InvokeRequired)
button1.Invoke(new MyDelegate(UpdateText));
button1.Text = "New Text";
或使用匿名方法:
void Start()
this.Invoke((MyDelegate)delegate
UpdateText();
);
private void UpdateText()
button1.Text = "New Text";
【讨论】:
嗨,腰带。感谢您的快速答复。但我不确定我们是否相互理解。我确实检查了表单是否需要调用调用。在我的情况下,我不更新控件,我只是想在表单上添加一个新控件。 差异不是很大——您必须创建要添加到与 Form 相同的线程中的控件(例如在 InitializeComponent 之后),而不是使用我描述的方法从单独的线程中添加它。 【参考方案4】:使用线程来添加按钮是非常昂贵的!请改用线程池。
【讨论】:
以上是关于从另一个线程在表单上添加控件的主要内容,如果未能解决你的问题,请参考以下文章