我无法直接找到任何东西来解决我的这个问题。我正在尝试为我的程序中加载时间较长的几个地方制作一个动画 gif 作为加载屏幕。
我让它在启动时工作,但是一旦我再次尝试使用它,它就会使我的程序崩溃。我从来没有完全理解整个线程,所以我的代码可能有问题。
[编辑]我想要的是在运行繁重的方法时让加载屏幕发生让我们说当它从数据库中获取所有数据或只是一个简单的 Thread.Sleep(####) 时,我想要一个动态的启动画面,运行在这个屏幕是我的第二个窗口的地方,上面有一个动画 gif。我让窗口和 gif 运行。
我将要检查的 Windows 是
- 主窗口.xaml
- 加载.xaml
- 应用程序.xaml
加载.xaml
此页面上唯一的内容是使用 WpfAnimatedGif 包的动画 gif。并且窗口的其余部分是透明的。
public partial class Loading : Window, ISplashScreen
{
public Loading()
{
InitializeComponent();
}
public void LoadStart()
{
Dispatcher.Invoke((Action)delegate()
{
//this.UpdateMessageTextBox.Text = message;
});
}
public void LoadComplete()
{
Dispatcher.InvokeShutdown();
}
}
public interface ISplashScreen
{
void LoadStart();
void LoadComplete();
}
}
应用程序.xaml
public partial class App : Application
{
public static ISplashScreen splashScreen;
private ManualResetEvent ResetSplashCreated;
private Thread SplashThread;
protected override void OnStartup(StartupEventArgs e)
{
// ManualResetEvent acts as a block. It waits for a signal to be set.
ResetSplashCreated = new ManualResetEvent(false);
// Create a new thread for the splash screen to run on
SplashThread = new Thread(ShowSplash);
SplashThread.SetApartmentState(ApartmentState.STA);
SplashThread.IsBackground = true;
SplashThread.Name = "Splash Screen";
SplashThread.Start();
// Wait for the blocker to be signaled before continuing. This is essentially the same as: while(ResetSplashCreated.NotSet) {}
ResetSplashCreated.WaitOne();
base.OnStartup(e);
}
private void ShowSplash()
{
// Create the window
Loading animatedSplashScreenWindow = new Loading();
splashScreen = animatedSplashScreenWindow;
// Show it
animatedSplashScreenWindow.Show();
// Now that the window is created, allow the rest of the startup to run
ResetSplashCreated.Set();
System.Windows.Threading.Dispatcher.Run();
}
}
}
主窗口.xaml
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Action that takes time here
App.splashScreen.LoadComplete();
}
private void _btnVisUKategorier_Click(object sender, RoutedEventArgs e)
{
App.splashScreen.LoadStart();
FyldUKategorier();
App.splashScreen.LoadComplete();
}
PS:如果您知道任何更好的解决方案可以与我在这里尝试做的相同,请随时提供链接。
[编辑]我改变了,所以我不再使用 app.xaml,因为我不想在我的启动中使用它我将代码移动到将要使用它的主窗口中。
它现在不再崩溃,但它只第一次显示我的窗口,除此之外的任何内容都不会显示任何内容。
[Edit-2]我进行了一些测试并决定让窗口看起来更好,这就是我遇到确切问题所在的时候。在我将上面的代码移到我的 Main 中而不是让它在 App.xaml 上运行之后,似乎上面的代码现在可以正常工作了。我删除了
public void LoadStart()
{
Dispatcher.Invoke((Action)delegate()
{
//this.UpdateMessageTextBox.Text = message;
});
}
也来自 Loading.xaml,因为我没有任何东西可以使用。在我关注的示例中,它用于更新页面本身的标签。
问题似乎出在我安装的应该向我展示动画 gif 的软件包上。
<Image gif:ImageBehavior.RepeatBehavior="Forever" gif:ImageBehavior.AnimatedSource="/img/Animated_ARKA_Loading.gif" />
新问题仍然是同一个项目
好的,所以下一个问题是当我显示加载屏幕时,它第一次运行时第二次运行,窗口为空。
使加载达到我想要的点的修复在下面的解决方案中,并且出现崩溃是因为我试图输入一个已关闭的线程。我想我可以用方法开始它,所以我最终删除了它。
主窗口
private void AnimatedLoading()
{
// ManualResetEvent acts as a block. It waits for a signal to be set.
ResetSplashCreated = new ManualResetEvent(false);
// Create a new thread for the splash screen to run on
SplashThread = new Thread(ShowSplash);
SplashThread.SetApartmentState(ApartmentState.STA);
SplashThread.IsBackground = true;
SplashThread.Name = "Splash Screen";
SplashThread.Start();
// Wait for the blocker to be signaled before continuing. This is essentially the same as: while(ResetSplashCreated.NotSet) {}
ResetSplashCreated.WaitOne();
FyldUKategorier();
splashScreen.LoadComplete();
SplashThread.Abort();
}
private void ShowSplash()
{
// Create the window
Loading loading = new Loading();
splashScreen = loading;
// Show it
loading.Show();
// Now that the window is created, allow the rest of the startup to run
ResetSplashCreated.Set();
System.Windows.Threading.Dispatcher.Run();
}
加载.xaml
public Loading()
{
InitializeComponent();
}
public void LoadComplete()
{
Dispatcher.InvokeShutdown();
}
}
public interface ISplashScreen
{
void LoadComplete();
}