Reputation: 8462
I'm trying to do a splash screen using CF.NET but I'm lost in the threading stuff.
What I have is a console project that dynamically loads (WinForm) screens (if exists, else output in Console).
What I want now is to be able to send messages to this form (running on a separate thread).
But this doesn't work, I cannot have a handle of my form in the current working thread.
This code works:
// Works but running in the current thread, so is blocking
// and that's not good
Assembly assembly = Assembly.LoadFrom("240x320Screens.dll");
Form ff = assembly.CreateInstance("Screens.Loader") as Form;
Application.Run(ff);
// The form implements this interface too
((ISplashView)ff).SetStep("Step 1 on 3");
Threaded code now (doesn't work):
Thread presenterThread = null;
Assembly assembly = Assembly.LoadFrom("240x320Screens.dll");
Form ff = assembly.CreateInstance("Screens.Loader") as Form;
presenterThread = new Thread((ThreadStart)(() =>
{
Application.Run(ff);
}));
presenterThread.Start();
((ISplashView)ff).SetStep("Step 1 on 3");
Thread.Sleep(5000);
((ISplashView)ff).SetStep("Step 2 on 3");
Thread.Sleep(5000);
((ISplashView)ff).SetStep("Step 3 on 3");
// Wait the user close the launcher (allowed in my case)
if (presenterThread != null)
presenterThread.Join();
But this throws :
Control.Invoke must be used to interact with controls created on a separate thread.
How can I fix this?
Thanks
Upvotes: 0
Views: 993
Reputation: 34519
The problem occurs because only the main UI thread is allowed to update UI controls. The way to get around this is to check the 'InvokeRequired' property on a control, create a delegate and execute the delegate using the control's Invoke method.
An easy implementation is to use the following static extension method:
public static void InvokeIfRequired<T>(this T control, Action<T> action) where T : Control
{
if (control.InvokeRequired)
{
control.Invoke(action, control);
}
else
{
action(control);
}
}
If you call it like so then everything will be handled for you:
this.textbox1.InvokeIfRequired(txt => txt.Text = "test");
Upvotes: 2