この問題を解決するために直接何かを見つけることができませんでした。読み込み時間が長いプログラムのいくつかの場所の読み込み画面として、アニメーション gif を作成しようとしています。
スタートアップで動作するようになりましたが、もう一度使用しようとすると、プログラムがクラッシュします。スレッド全体を完全に理解したことがないため、コードに何か問題がある可能性があります。
[編集]私が望むのは、重いメソッドが実行されているときにロード画面を表示することです。たとえば、データベースからすべてのデータを取得するとき、または単純な Thread.Sleep(####) を取得するときです。この画面はアニメーション GIF が表示された 2 番目のウィンドウです。ウィンドウとgifを実行しました。
これから取り上げる Windows は
- MainWindow.xaml
- 読み込み中.xaml
- App.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();
}
}
App.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();
}
}
}
MainWindow.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 を使用しないように変更しました。これは、スタートアップで使用したくないためです。コードを使用するメインウィンドウに移動しました。
今はもうクラッシュしていませんが、最初にウィンドウが表示されるだけで、これ以降は何も表示されません。
[編集-2]いくつかのテストを実行し、ウィンドウの見栄えを良くすることにしました。そのとき、正確な問題がどこにあるのかを突き止めました。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" />
新しい問題はまだ同じプロジェクト
さて、これの次の問題は、ロード画面を表示すると、最初に動作し、2回目に実行するとウィンドウが空になることです。
Loading を必要なポイントまで取得するための修正は、以下のソリューションにあり、閉じられたスレッドに入ろうとしたためにクラッシュが発生しました。メソッドで始められると思ったので、結局削除しました。
メインウィンドウ
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();
}