我正在尝试使用CF.NET进行启动画面,但我迷失在线程中。
我所拥有的是一个动态加载(WinForm)屏幕的控制台项目(如果存在,则在Console中输出)。
我现在想要的是能够向此表单发送消息(在单独的线程上运行)。
但这不起作用,我无法在当前工作线程中处理我的表单。
此代码有效:
// 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");
现在使用线程代码(不起作用):
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();
但是这引发了:
必须使用Control.Invoke与在单独线程上创建的控件进行交互。
我该如何解决这个问题?
由于
答案 0 :(得分:2)
出现此问题是因为只允许主UI线程更新UI控件。解决这个问题的方法是检查控件上的'InvokeRequired'属性,创建一个委托并使用控件的Invoke方法执行委托。
一个简单的实现是使用以下静态扩展方法:
public static void InvokeIfRequired<T>(this T control, Action<T> action) where T : Control
{
if (control.InvokeRequired)
{
control.Invoke(action, control);
}
else
{
action(control);
}
}
如果您这样打电话,那么一切都将为您处理:
this.textbox1.InvokeIfRequired(txt => txt.Text = "test");