当我使用线程调用另一个表单并显示它时,组件(标签)无法正常工作

Posted

技术标签:

【中文标题】当我使用线程调用另一个表单并显示它时,组件(标签)无法正常工作【英文标题】:When I use Threads to Call Another Form and Show it, The Components (the label) doesn't work properly 【发布时间】:2017-06-08 10:49:25 【问题描述】:

所以,为了学习如何使用线程,我制作了一个小程序,它应该接收名称并将它们存储在一个列表中,然后以另一种形式依次显示名称。 所以,这里是代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace ListingThread

public partial class Form1 : Form

    public Thread t;
    public static int ShowNo = 0;
    public Form1()
    
        InitializeComponent();
        GlobalForm = new Form();
        GlobalForm.Show();
        GlobalForm.Hide();
        t = new Thread(ShowList);
    
    public Form GlobalForm;
    public static List<string> Names = new List<string>();
    private void Form1_Load(object sender, EventArgs e)
    

    

    private void btnAddName_Click(object sender, EventArgs e)
    
        AddName(txtName.Text);
        txtName.Text = null;
    
    public void AddName(string x)
    
        Names.Add(x);
    

    private void btnShow_Click(object sender, EventArgs e)
    
        Showw();
    
    public void Showw()
    
        t.Start();
    
    public void ShowList()
    
        if (ShowNo < Names.Capacity)
        

            GlobalForm.Invoke((MethodInvoker)delegate ()
            
                CustomMessageBox Msg = new CustomMessageBox();
                try  Msg.lblName.Text = Names[ShowNo];
                
                catch
                
                    t.Abort();
                
                Msg.Show();
                Thread.Sleep(500);
                Msg.Close();
                ShowNo++;
                ShowList();
            );
        
        else
        
            t.Abort();
        
    


另一种形式只有一个名为 lblName 的标签:

但是当我运行时会发生这种情况:/:

如您所见,标签无法正常工作:/ 它们显示如下:

【问题讨论】:

ShowNo &lt; Names.Capacity -> Names.Count 也许? 我把它改成了你说的,但还是不行:/。我觉得这里的问题有点复杂。 我相信表单必须在 UI 线程上运行。 真的很简单。您正在睡觉,这会阻止标签刷新。请改用计时器。您可以在睡眠电话之前拨打Msg.Refresh(); 作弊。顺便说一句,这不是学习线程的最佳方式。线程用于操作长时间运行的操作,例如数据检索、分析等。任何 GUI 的东西都必须在主线程上发生。您的 GlobalForm 不是很有用。 你正在休眠 UI 线程,它阻塞了对 Invoke 的调用。您是否尝试过使用BeginInvoke 而不是Invoke?这不应该阻塞,它只是将调用排队。 【参考方案1】:

我建议使用Timer 而不是Thread.Sleep,以免阻塞 UI 线程,因为休眠会阻止标签更新。

while (ShowNo < Names.Count)
        
            CustomMessageBox Msg = new CustomMessageBox();
            GlobalForm.Invoke((MethodInvoker)delegate()
            
                try
                
                    Msg.lblName.Text = Names[ShowNo];
                    Msg.Show();
                    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
                    timer.Interval = 2000;
                    timer.Tick += (s, e) => Msg.Close();
                    timer.Start();
                
                catch
                
                    t.Abort();
                
                ShowNo++;
            );
        

顺便说一句,一旦线程完成运行,就无需中止它。我也会使用 while 循环而不是递归方法调用。

【讨论】:

以上是关于当我使用线程调用另一个表单并显示它时,组件(标签)无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

从另一个不同的 AngularJS 组件访问表单(用于验证)

如何在另一个组件中使用来自组件的表单

我想在更改时保存表单,并使用 laravel 和 Jquery 创建一个动态表单

dispatch 不调用reducer React Native

当我进入另一个组件(角度2/4/5)的主题调用的订阅方法时,为什么我在控制台中看不到我的根变量组件?

vue3 路由器不显示我的组件