我试图推迟向我的主要表单添加控件,目标是加快它的开始时间。好吧,我遇到以下例外:
跨线程操作无效: 控制从线程访问的'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是否为true,但InvokeRequiered保持“true”。我真的不明白。至少我会期待StackOverflow异常,因为这是一个递归调用。
所以,如果有人遇到类似的问题,请告诉我,我做错了什么?
答案 0 :(得分:5)
您的代码中的问题是您正在添加两个按钮。
将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);
}
}
答案 1 :(得分:1)
您可以这样做......
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);
});
}
答案 2 :(得分:0)
请改用匿名方法。说明如下。
如果我们有这样的形式:
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";
}
答案 3 :(得分:0)
使用线程添加按钮非常昂贵!请改用ThreadPool。