Home > Software engineering >  How to call method in Form class from thread
How to call method in Form class from thread

Time:12-09

I'm trying to make a simple clock program with threads. In Form1 I want to create a new thread that's in ThreadProc(), take time, and sent back to Form1 send() method that will replace the text in label.

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            ThreadProc tP = new ThreadProc();
            Thread t = new Thread(tP.threadP);
            t.Start();
        }
        public void send(Object obj)
        {
            string time;
            try
            {
                time = (string)obj;
            }
            catch (InvalidCastException)
            {
                time = " ";
            }
            if (label1.InvokeRequired)
                this.Invoke((MethodInvoker)delegate () { label1.Text = time; });
            else
                label1.Text = time;
        }


    }
internal class ThreadProc
    {
        public void threadP()
        {        
            Form1 form1 = new Form1();
            DateTime dateTime;
            do
            {
                dateTime = DateTime.Now;
                string time = dateTime.ToString(); 
                Thread t = new Thread(() => form1.send(time));
                t.Start();
                Thread.Sleep(500);
            } while (true);
        }
    }

It ends up in infinite loop of Form1() -> threadP() -> Form1()... but without

Form1 form1 = new Form1();

I can't call send() in

Thread t = new Thread(() => form1.send(time));

The threadP() has to be in their own class and send() has to be in Form1 class.

CodePudding user response:

Pass a reference to your form to the thread. You can then access it from there.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        ThreadProc tP = new ThreadProc();
        Thread t = new Thread(tP.threadP);

        // Automatically end thread when application ends
        t.IsBackground = true;
        
        // Pass reference to this form to thread
        t.Start(this);
    }

    public void Send(string time)
    {
        if (Visible) // Check form wasn't closed
        {
            if (label1.InvokeRequired)
                this.Invoke((MethodInvoker)delegate () { label1.Text = time; });
            else
                label1.Text = time;
        }
    }
}

internal class ThreadProc
{
    public void threadP(object data)
    {
        // Get Form1 reference from start parameter
        Form1 form1 = data as Form1;
        
        DateTime dateTime;
        do
        {
            dateTime = DateTime.Now;
            string time = dateTime.ToString();
            form1.Send(time);
            Thread.Sleep(500);
        } while (true);
    }
}

Note that there are better designs to re-use the thread like passing an interface instead of the concrete Form1 class. But this is just a simple example.

When a Form and a background thread are so closely bound together, you usually use a BackgroundWorker instead of threads.

  • Related