Search code examples
c#multithreadingvisual-studioinvoke

When I use Threads to Call Another Form and Show it, The Components (the label) doesn't work properly


So, For the sake of learning how to use threading I made a little program that is supposed to take in names and store them in a list and then show the names in another form one after another. So, here is the code:

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();
        }
    }
}
}

The Other form simply has one label named lblName: The Second Form

But When I run this happens :/ : Program Running

As you can see, the labels don't work properly :/ They are shown like this: Broken Label


Solution

  • I would suggest using a Timer instead of Thread.Sleep so as to not block the UI thread, as sleeping will prevent the label from updating.

    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++;
                });
            }
    

    As an aside, there's no need to abort the thread once it's finished running. I'd also use a while loop instead of a recursive method call.