代码之家  ›  专栏  ›  技术社区  ›  Giora Guttsait

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

  •  2
  • Giora Guttsait  · 技术社区  · 9 年前

    我有一个名为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 回复  |  直到 9 年前
        1
  •  3
  •   The Vermilion Wizard    9 年前

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

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

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