【发布时间】:2015-06-11 02:11:37
【问题描述】:
我有一个 Windows 窗体应用程序,它应该显示一个带有标签字段的初始屏幕,我想在后台加载主窗体(称为welcome.cs)时更新该标签字段。初始屏幕显示和隐藏得很好,但标签没有更新。
我做了很多研究,但还没有找到解决方案。
程序.cs
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (new SingleGlobalInstance(1000))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SplashScreen splashscreen = new SplashScreen();
splashscreen.ShowSplashScreen();
Welcome welcome = new Welcome(splashscreen); //Takes some time to load
splashscreen.CloseForm();
Application.Run(welcome);
}
}
Splashscreen.cs
public partial class SplashScreen : Form
{
//Delegate for cross thread call to close
private delegate void CloseDelegate();
private delegate void UpdateStatusDelegate(string status);
private static SplashScreen splashScreen;
private Thread thread = null;
public SplashScreen()
{
InitializeComponent();
}
public void ShowSplashScreen()
{
// Make sure it is only launched once.
if (splashScreen != null)
return;
thread = new Thread(ShowForm);
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
static private void ShowForm()
{
splashScreen = new SplashScreen();
Application.Run(splashScreen);
}
public void CloseForm()
{
splashScreen.Invoke(new CloseDelegate(CloseFormInternal));
}
static private void CloseFormInternal()
{
splashScreen.Close();
}
public void UpdateStatus(string status)
{
splashScreen.Invoke(new UpdateStatusDelegate(UpdateStatusInternal), status);
}
private void UpdateStatusInternal (string status)
{
if (splashScreen != null && splashScreen.IsHandleCreated)
{
lblStatus.Text = status;
}
}
}
Welcome.cs
public Welcome(Splashscreen splashscreen)
{
InitializeComponent();
//Code to log the user into the system
splashScreen.UpdateStatus("Logging in...");
//my expectation is that UpdateStatus call will update the label displayed on the splash screen but it doesn't.
//Do more stuff.....
}
它与多线程有关还是因为我在调用 UpdateStatus 之前在welcome.cs 中创建了一个新的启动画面实例?我该如何解决这个问题?
【问题讨论】:
-
您正在
Welcome表单中创建一个新SplashScreen,而不是引用您已经显示的那个。您需要将现有初始屏幕的引用传递给Welcome表单的构造函数,以便使用该现有引用。 -
我错过了您尝试拥有多个 UI 线程的情况?那是非常错误的,删除创建自己的线程以运行的部分。您还不止一次拨打
Application.Run,不建议这样做。 -
它不起作用的原因是您在主例程中创建的引用也不是显示的实例,您创建了一个新的、私有的启动屏幕实例作为某种单例模式的错误尝试。按照您的编码方式,您无法获得对显示表单的实际引用。
-
在阅读了您关于无法获得实际参考的评论后,我将 ShowSplashScreen、CloseForm、UpdateStatus 转换为静态方法。现在只有一个 SplashScreen 实例是在 ShowForm 中创建的。然后我在 SplashScreen 表单中添加了一个计时器,用于更新 lblStatus。有用!!但是,我会将其作为临时解决方案记录下来,并且肯定会对此主题进行更多研究以改进我的代码。
标签: c# winforms splash-screen