使用Task.Run运行时用户控件卡住了

时间:2015-09-24 22:01:33

标签: c# winforms monogame

我有一个名为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实例打开,它被卡住,而用户控制的位置应该是,它显示透明空间,显示它背后的部分和游戏形式,
几秒钟后,表格就会消失 再次重新打开表单会导致相同的错误

Image of the problem

我在这里做错了什么?

编辑:固定代码,在此处显示,以防有人想要查看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);
});

1 个答案:

答案 0 :(得分:3)

您不应该从任务创建表单。表单有一个消息泵,它只能在创建它们的线程上运行。此消息泵处理输入事件,绘图事件等。

使用Task.Run运行代码时,它在线程池线程上运行。这意味着分配了一个线程来运行代码,一旦完成该线程就会返回到线程池并且不再运行任何代码。由于您没有在该线程上显式运行消息泵,因此不会处理任何更新事件,并且表单将会像它已经死了一样。

最简单的方法是在与所有其他表单相同的线程上创建和运行表单。除此之外,您应该使用Thread对象来创建表单并在该线程上使用Application.Run(myForm)以便处理其消息。