运行 和 Task.Run 时用户控件卡住
User Control stuck when ran with Task.Run
我有一个名为 ItemControl 的用户控件。
public partial class ItemControl : UserControl
{
public ModuloFramework.ItemSystem.Item Item { get; set; }
public ItemControl(ModuloFramework.ItemSystem.Item item)
{
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
Item = item;
}
private void ItemControl_Load(object sender, System.EventArgs e)
{
itemNameLabel.Text = Item.Name;
itemTypeLabel.Left = itemNameLabel.Right + 5;
itemTypeLabel.Text = Item.Type.ToString();
itemPriceLabel.Left = itemTypeLabel.Right + 5;
itemPriceLabel.Text = Item.Price.ToString();
itemDescriptionLabel.Text = Item.Description;
}
}
我有另一种形式,只是一个测试:
public partial class Form1 : Form
{
public List<ModuloFramework.ItemSystem.Item> Items { get; set; }
private Button EscapeButton { get; }
public Form1(List<ModuloFramework.ItemSystem.Item> items)
{
InitializeComponent();
Items = items;
EscapeButton = new Button()
{
Enabled = false,
Visible = false
};
EscapeButton.Click += (sender, args) => Close();
}
private void Form1_Load(object sender, EventArgs e)
{
this.CancelButton = EscapeButton;
int y = 0;
foreach (Item item in Items) {
ItemControl control = new ItemControl(item);
control.Left = 0;
control.Top = y;
y += control.Height + 3;
panel1.Controls.Add(control);
}
}
}
这是调用表单的上下文:
Task.Run(() =>
{
List<Item> items = new List<Item>()
{
TestItem.Item1,
TestItem.Item2
};
Form1 form = new Form1(items);
form.Show();
});
当我尝试 运行 时发生的事情是,Form1 实例打开并卡住,而用户控件应该在的地方显示透明 space ,展示了它背后的部分和游戏形式,
几秒钟后,表格消失了。
再次重新打开表单会导致相同的错误
我做错了什么?
编辑:修复代码,在此处显示以防有人想查看 Erik 修复的示例
List<Item> items = new List<Item>()
{
TestItem.Item1,
TestItem.Item2,
TestItem.Item1,
TestItem.Item2
};
Form1 form = new Form1(items);
form.Show();
Thread trd = new Thread(() =>
{
Application.Run(form);
});
您不应从任务创建表单。表单有一个消息泵,它只能在它们创建的线程上运行。此消息泵处理输入事件、绘图事件等。
当您使用 Task.Run
运行 代码时,它 运行 在线程池线程上。这意味着一个线程被分配给 运行 代码,一旦完成,该线程将返回到线程池并且不再 运行 任何代码。由于您没有明确地 运行 在该线程上启用消息泵,因此不会处理任何更新事件,并且表单将像死了一样。
最简单的方法是在与所有其他表单相同的线程上创建和 运行 表单。除此之外,您应该使用 Thread
对象来创建表单并在该线程上使用 Application.Run(myForm)
以便处理其消息。
我有一个名为 ItemControl 的用户控件。
public partial class ItemControl : UserControl
{
public ModuloFramework.ItemSystem.Item Item { get; set; }
public ItemControl(ModuloFramework.ItemSystem.Item item)
{
Control.CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
Item = item;
}
private void ItemControl_Load(object sender, System.EventArgs e)
{
itemNameLabel.Text = Item.Name;
itemTypeLabel.Left = itemNameLabel.Right + 5;
itemTypeLabel.Text = Item.Type.ToString();
itemPriceLabel.Left = itemTypeLabel.Right + 5;
itemPriceLabel.Text = Item.Price.ToString();
itemDescriptionLabel.Text = Item.Description;
}
}
我有另一种形式,只是一个测试:
public partial class Form1 : Form
{
public List<ModuloFramework.ItemSystem.Item> Items { get; set; }
private Button EscapeButton { get; }
public Form1(List<ModuloFramework.ItemSystem.Item> items)
{
InitializeComponent();
Items = items;
EscapeButton = new Button()
{
Enabled = false,
Visible = false
};
EscapeButton.Click += (sender, args) => Close();
}
private void Form1_Load(object sender, EventArgs e)
{
this.CancelButton = EscapeButton;
int y = 0;
foreach (Item item in Items) {
ItemControl control = new ItemControl(item);
control.Left = 0;
control.Top = y;
y += control.Height + 3;
panel1.Controls.Add(control);
}
}
}
这是调用表单的上下文:
Task.Run(() =>
{
List<Item> items = new List<Item>()
{
TestItem.Item1,
TestItem.Item2
};
Form1 form = new Form1(items);
form.Show();
});
当我尝试 运行 时发生的事情是,Form1 实例打开并卡住,而用户控件应该在的地方显示透明 space ,展示了它背后的部分和游戏形式,
几秒钟后,表格消失了。
再次重新打开表单会导致相同的错误
我做错了什么?
编辑:修复代码,在此处显示以防有人想查看 Erik 修复的示例
List<Item> items = new List<Item>()
{
TestItem.Item1,
TestItem.Item2,
TestItem.Item1,
TestItem.Item2
};
Form1 form = new Form1(items);
form.Show();
Thread trd = new Thread(() =>
{
Application.Run(form);
});
您不应从任务创建表单。表单有一个消息泵,它只能在它们创建的线程上运行。此消息泵处理输入事件、绘图事件等。
当您使用 Task.Run
运行 代码时,它 运行 在线程池线程上。这意味着一个线程被分配给 运行 代码,一旦完成,该线程将返回到线程池并且不再 运行 任何代码。由于您没有明确地 运行 在该线程上启用消息泵,因此不会处理任何更新事件,并且表单将像死了一样。
最简单的方法是在与所有其他表单相同的线程上创建和 运行 表单。除此之外,您应该使用 Thread
对象来创建表单并在该线程上使用 Application.Run(myForm)
以便处理其消息。