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.