Laden...

SplashScreen - Statustext Updaten

Erstellt von reloop vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.415 Views
reloop Themenstarter:in
139 Beiträge seit 2010
vor 12 Jahren
SplashScreen - Statustext Updaten

Hallo liebe Community,

ich habe folgendes Problem:

Ich möchte meiner Application einen "SplashScreen" verpassen. Dafür habe ich meiner Anwendung ein Window mit dem Namen "SplashWindow" hinzugefügt. Dieses Window enthält ein Label mit dem Namen "txtStatus".

Zur Aktualisierung dieses Textes existiert eine Methode:

SplashWindow.xaml.cs


public void SetStatusText(string text)
{
     if (!txtStatus.Dispatcher.CheckAccess ()) { 
            txtStatus.Dispatcher.Invoke ((Action)delegate { SetStatusText(text); });
      return;
   }
   
   txtStatus.Text = text;
}

Nun instanziiere ich im App (Codebehind) wie folgt den SplashScreen & das MainWindow:

App.xaml.cs



SplashWindow _splashWindow;
....OnStartup()
{
   _splashWindow = new SplashWindow();
   _splashWindow.Show();

   var mainWindow = new MainWindow();
   mainWindow.Show();
   mainWindow.OnSetStatus = SetStatusText;
}

private void SetStatusText(string text)
{
    _splashWindow.SetStatusText(text);
}

Soweit so gut, und zum Schluss existiert im Loaded-Event vom MainWindow folgender Aufruf:

MainWindow.xaml.cs


...

public .... Loaded
{
  OnSetStatus("Daten werden geladen...");
  HoleDaten();
  OnSetStatus("Alle Daten wurden erfolgreich geladen.");
}

...

Es funktioniert alles auch soweit, bei dem Aufruf "OnSetStatus" wird der gesamte Code bishin zum "txtStatus.Text = text" durchlaufen. Jedoch updatet sich die Gui erst beim Beenden der OnStartUp-Methode.

Was mache ich falsch?

Ich habe mich an folgendem Beispiel orientiert:
[

[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)](http://www.mycsharp.de/wbb2/thread.php?threadid=33113)

Kam jedoch nicht zum gewünschten Ergebnis.

Vielleicht habt ihr ja einen Tipp für mich.

Gruss

643 Beiträge seit 2006
vor 12 Jahren

WPF hat 2 Threads. Einen womit du arbeitest und einen der alles Zeichnet. Damit die Benutzeroberfläche nicht mehr einfriert beim Zeitaufwändigen unterfangen.

Du musst vermutlich die OnStartup Methode von der Application class aufrufen, damit der Zeichenthread startet.

protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
}

reloop Themenstarter:in
139 Beiträge seit 2010
vor 12 Jahren

Hallo Ayke,

hat leider keine Veränderung gebracht. Trotzdem danke für die Hilfe!

Hat vielleicht noch jemand eine Idee?

Gruss,
reloop

114 Beiträge seit 2009
vor 12 Jahren

Also ich bin der Meinung, dass du dein holeDaten() wohl manuell in einen eigenen Thread pusten musst. Soweit ich das erkenne laufen in WPF alle Methode immernoch im GUI-Thread. Wäre ja auch doof wenn nicht, da man ansonsten für jeden Zugriff auf die GUI diesen Handstand machen müsste.

Das kann man auch schön erkennen, wenn man z.B. einen Button mit einem langen Prozess auf die GUI legt, bleibt der Button eingedrückt bis die Aktion abgeschlossen ist.

Oder gibt es ab WPF eine hübschere Variante?

Gruß

Levi

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            new Thread(new ThreadStart(myProcess)).Start();
        }

        private void myProcess()
        {
             for (int i = 0; i < 1000000; i++)
             {
                setStatusText(i.ToString());
             }
        }

        private void setStatusText(string text)
        {
            if (!textBox1.Dispatcher.CheckAccess())
            {
                textBox1.Dispatcher.Invoke(new Action(delegate()
                {
                    textBox1.Text = text;
                }));

                return;
            }

            textBox1.Text = text;
        }
    }
}

643 Beiträge seit 2006
vor 12 Jahren

Das kann man auch schön erkennen, wenn man z.B. einen Button mit einem langen Prozess auf die GUI legt, bleibt der Button eingedrückt bis die Aktion abgeschlossen ist.

Das wäre wohl anderes auch nicht möglich. Der Button wird aber trotzdem neu gezeichnet, auch wenn er so lange verhaart bis die Aktion abgeschlossen ist.
Das sieht man am besten wenn man den GUI Thread arbeiten schickt und dann mit einen anderen Fenster drüber fährt. Bei Windows Forms hast mann dann ein buntes Fenster. Das wird dann aber wahrscheinlich irgendwo in der Milcore Bibliothek geregelt.

Das verhalten ist irgendwie eigenartig. Habe mal in der Main Methode folgendes versucht. Erst wenn die Application Klasse eine "MessageLoop?" erstellt, werden die Fenster aktualisiert. Das hat wohl eher nix wie in meiner vorherigen Vermutung mit den "Zeichenthread" zu tun.

        [System.STAThreadAttribute()]
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public static void Main() {
            MainWindow window = new MainWindow();
            window.label1.Content = "Me";
            Thread.Sleep(10000);
            //WpfApplication1.App app = new WpfApplication1.App();
            //app.Run();
        }