C# 与任务一起运行时用户控件被卡住。运行

C# 与任务一起运行时用户控件被卡住。运行,c#,winforms,monogame,C#,Winforms,Monogame,我有一个名为ItemControl的用户控件 public partial class ItemControl : UserControl { public ModuloFramework.ItemSystem.Item Item { get; set; } public ItemControl(ModuloFramework.ItemSystem.Item item) { Control.CheckForIllegalCrossThreadCalls

我有一个名为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;
    }
}
我有另一张表格,只是一张ofc的测试表:

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);
        }
    }
}
公共部分类表单1:表单
{
公共列表项{get;set;}
私有按钮转义按钮{get;}
公共表格1(列表项目)
{
初始化组件();
项目=项目;
EscapeButton=新按钮()
{
启用=错误,
可见=假
};
转义按钮。单击+=(发送者,参数)=>Close();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
this.CancelButton=EscapeButton;
int y=0;
foreach(项目中的项目){
ItemControl=新的ItemControl(项目);
对照组:左=0;
控制。顶部=y;
y+=控制高度+3;
面板1.控件。添加(控件);
}
}
}
这是调用表单的上下文:

Task.Run(() =>
{
    List<Item> items = new List<Item>()
    {
        TestItem.Item1,
        TestItem.Item2
    };
    Form1 form = new Form1(items);
    form.Show();
});
Task.Run(()=>
{
列表项=新列表()
{
测试项目1,
测试项目2
};
Form1 form=新的Form1(项目);
form.Show();
});
当我试着运行它时,会发生的情况是Form1实例打开,它卡住了,而用户控件应该在的地方,它显示了透明的空间,显示了它和游戏表单后面的部分,
几秒钟后,表单死亡。
再次打开表单会导致相同的错误

我做错了什么


编辑:修复代码,在这里显示,以防有人想看到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);
});
List items=新列表()
{
测试项目1,
测试项目2,
测试项目1,
测试项目2
};
Form1 form=新的Form1(项目);
form.Show();
线程trd=新线程(()=>
{
申请表格;
});

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

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


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

Control.CheckForIllegalCrossThreadCalls=false?这通常是一件坏事。这是我从另一个帖子里想到的。。。试了一下,没用。我会确保删除它非常搞笑如何邪恶的代码是可以通过窗口看到的。哈哈:D正如我所说,这只是一个尝试。。。召唤反基督者。了不起的家伙,做了那件事,我学到了Winforms的一件好事。谢谢