不确定这是最好的标题。
我的线程遇到了一些问题。在Application_Startup
中,我启动了一个新线程,在静态助手类的帮助下打开了一个简单的启动画面窗口。在Application_Startup
中,有一种检查用户是否已登录的方法,如果他尚未登录,则会打开登录窗口。此时,如果出现登录窗口,则启动画面应为close
,但它不会。
private void Application_Startup(object sender, StartupEventArgs e)
{
Thread thread = new Thread(
new ThreadStart(
delegate ()
{
SplashScreenHelper.SplashScreen = new Splash()
// this works. the splash screen opens
SplashScreenHelper.Show();
System.Windows.Threading.Dispatcher.Run();
}
));
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
check();
}
private void check()
{
var clientid = (int) IPdevices.Properties.Settings.Default["clientid"];
if (clientid > 0)
{
try
{
// this works
SplashScreenHelper.ShowText("Looking for profile...");
}
catch (EntityException)
{
}
}
else
{
// This does not work
SplashScreenHelper.Close();
// this opens up fine.
openLoginWindow();
}
}
当我们在else
方法中遇到check
条件时,事情开始失败。首先,我在SplashScreenHelper.Close();
中设置了一个断点,发现Splash
的实例为空,因此来自Close
窗口的Splash
从未触发(请参阅下面的课程)。但令人感到好奇的是,如果它被正确实例化并显示启动画面窗口,它怎么能为null?
这是SplashScreenHelper
课程,以获得一个想法:
class SplashScreenHelper
{
public static Splash SplashScreen { get; set; }
public static void Show()
{
if (SplashScreen != null)
{
SplashScreen.Show();
}
}
public static void Close()
{
if (SplashScreen == null) return;
if (!SplashScreen.Dispatcher.CheckAccess())
{
SplashScreen.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(delegate()
{
System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown();
SplashScreen.Close();
}));
}
else
{
SplashScreen.Close();
}
}
public static void ShowText(string text)
{
if (SplashScreen == null) return;
if (!SplashScreen.Dispatcher.CheckAccess())
{
SplashScreen.Dispatcher.Invoke(
DispatcherPriority.Normal,
new Action(delegate ()
{
((SplashScreenViewModel)SplashScreen.DataContext).SplashScreenText = text;
}
));
}
else
{
((SplashScreenViewModel)SplashScreen.DataContext).SplashScreenText = text;
}
}
}
当我们点击else
时,我有两个窗口:启动画面窗口和登录窗口,虽然启动窗口应该已经关闭但是它没有,因为启动画面实例是{{ 1}}这是我无法弄清楚会发生什么的地方。
我认为发生的事情是,null
方法以某种方式在线程启动之前触发,打开登录窗口,点击else语句,尝试关闭启动画面但是启动画面线程从未启动过并且从未实例化它。 然后,然后线程最终实例化启动屏幕。
答案 0 :(得分:0)
在调用check
之前,您需要确保第二个线程中代码的第一部分运行。
ManualResetEvent对此非常有用!
using (ManualResetEvent mre = new ManualResetEvent(false))
{
Thread thread = new Thread(new ThreadStart(
delegate ()
{
SplashScreenHelper.SplashScreen = new Splash()
// this works. the splash screen opens
SplashScreenHelper.Show();
mre.Set(); // signal that we are done setting up the splash screen
System.Windows.Threading.Dispatcher.Run();
}
));
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
mre.WaitOne(); // wait until the signal is received
}
check(); // now we can safely call check()