Ich habe dieses Forum durchsucht (nach SplashScreen, Splash und Screen) und auch einige verlinkte Threads durchgelesen und eigentlich (dachte ich zumindest) auch verstanden (bloss kein Application.DoEvents einsetzen).
Nun habe ich mal ein kleines Testprogramm erstellt und festgestellt, dass ich wohl doch einiges nicht verstanden habe.
Hier mal ein paar Auszüge meiner kreativen Ergüsse:
Program.cs
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using (frmSplash splash = new frmSplash())
{
splash.Text = String.Empty;
splash.ControlBox = false;
splash.StartPosition = FormStartPosition.CenterScreen;
splash.ShowInTaskbar = false;
splash.TopMost = true;
splash.Show();
splash.Update();
//Application.DoEvents();
//Simulation einer längeren Initialisierung
for (int i = 0; i < 299; i++)
{
Thread.Sleep(1);
}
//Thread.Sleep(5000);
splash.Close();
}
using (Form1 frmHaupt = new Form1())
{
frmHaupt.StartPosition = FormStartPosition.CenterScreen;
Application.Run(frmHaupt);
}
}
Problem:
Der Splash wird angezeigt, aber nicht weiter aktualisiert. Konkret heißt das: die .Update Methoden zeigen keine Wirkung.
Nach ein wenig debugging ist mir aufgefallen, dass die Timer-Ticks gar nicht ausgeführt werden.
Ich habe das ganze auch noch mal als Anhang gepostet, damit ihr auch versteht was ich eigentlich meine/will. Das lässt sich halt schwer beschreiben.
Frage:
Welchen Hinweis oder Wink (mit dem Zaun) könnt ihr mir geben, so dass sich der SplashScreen richtig aufbaut bzw. was kann ich an meinem Splash besser/eleganter machen?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Froggie am .
EDIT
Ich habe festgestellt, dass nicht einmal das Shown-Event des Splash ausgelöst wurde.
Weiterhin konnte ich beobachten, dass das Tick-Event des FadeIn-Timers nicht einmal aufgerufen wird.
Weiß jemand wieso?
Im Anhang ist ein aktualisiertes Projekt.
EDIT ENDE
Ich habe mir das zwar durchgelesen gehabt, aber irgendwie habe ich es erst jetzt verstanden.
Ich habe das nun in einen anderen Thread ausgelagert, aber der Splash wird immer noch nicht aktualisiert.
Der SplashScreen ist immer noch wie oben implementiert.
Ich hatte versucht einen Screenshot zu erstellen, aber da der Splash durchsichtig ist, sieht man nix (oder Cropper kommt damit nicht klar).
Program.cs
public class Program
{
frmSplash splash;
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Program program = new Program();
program.splash = new frmSplash();
program.splash.Text = String.Empty;
program.splash.ControlBox = false;
program.splash.StartPosition = FormStartPosition.CenterScreen;
program.splash.ShowInTaskbar = false;
program.splash.TopMost = true;
program.splash.Show();
program.splash.Update();
//HintergrundThread erstellen
ParameterizedThreadStart threadstart = new ParameterizedThreadStart(program.longRunning);
Thread worker = new Thread(threadstart);
worker.IsBackground = true;
//Wie bekomme ich einen Thread aus dem ThreadPool?
bool test = worker.IsThreadPoolThread;
worker.Start(9999);
//warten bis HintergrundThread erstellt wurde
while (!worker.IsAlive)
{
Thread.Sleep(1);
}
//warten bis HintergrundThread fertig ist
worker.Join();
//SplashScreen schließen
program.splash.Close();
//Hauptformular anzeigen
using (Form1 frmHaupt = new Form1())
{
frmHaupt.StartPosition = FormStartPosition.CenterScreen;
Application.Run(frmHaupt);
}
}
private void longRunning(object parameter)
{
for (int i = 0; i < (int)parameter; i++)
{
Debug.WriteLine("Bin zurzeit bei: " + i.ToString());
Thread.Sleep(1);
}
}
}
Frage(n):
Gibt es noch einen Hinweis warum der Splashscreen nicht richtig angezeigt wird? Nicht richtig angezeigt heißt, dass der FadeIn Effekt nur 1mal aufgrufen wird.
Der von mir erstellte Thread ist ja KEIN Thread aus dem ThreadPool. Ich muss allerdings warten bis der Thread fertig ist. Gibt es diese Möglichkeit auch mit Threads aus dem Pool?
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Froggie am .
Ich bin gerade am Umbauen meines Testprojektes. Bis jetzt habe ich den Splashscreen immer normal über die .Show-Methode angezeigt. Werde das jetzt testen, wie das aussieht, wenn ich den SplashScreen mit Application.Run(Splash) aufrufe.
Das soll deutlich einfacher gehen. ABER:
Meines Wissens nach wird so ein weiterer GUI-Thread erstellt. Und genau das wollte ich ja verhindern. Aber wenn es nicht anders bzw. das andere zu kompliziert ist, dann mache ich das halt mit 2 GUI-Threads.
Hat jemand berechtigte Einwände dagegen?
es ist nicht nötig und nicht sinnvoll zwei GUI-Thread zu verwenden.
Application.Run ist natürlich erforderlich, aber es gibt keinen Grund das Application.Run nicht im Haupt-Thread zu machen. Es muss ja nur die langlaufenden Aktion und nicht die Erzeugung und Anzeige des Splash-Screens im Worker-Thread erfolgen. Du solltest dazuwischen klar trennen.
Obwohl alles was ich jetzt schreibe, aus der FAQ hervorgeht, hier mal alles auf einen Blick: im Haupt-Thread das Splash-Fenster erzeugen, den Worker-Thread starten und Application.Run für das Splash aufrufen. An Ende des Worker-Threads, wie in der FAQ gezeigt, das Splash-Fenster schließen. Anschließend im Haupt-Thread ein zweites Application.Run für das eigentliche (Haupt-)Form. Fertig!
Warum schaut eigentlich niemand mal, was das Framework diesbezüglich anbietet?
Seit FW2 bietet WindowsFormsApplicationBase schon solche sachen an.
SplashScreenunterstützung, Abfangen von Mehrfachstart, Start und Stop Behandlung usw.
Warum schaut eigentlich niemand mal, was das Framework diesbezüglich anbietet?
der vollqualifiziere Klassenname lautet: Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.
Die Gründe könnten also sein:
Microsoft statt System: sprich weniger portabel.
VisualBasic statt CSharp: Sicher kann man in .NET sprachübergreifend programmieren, aber wenn die Klassen tatsächlich von allgemeiner Bedeutung sind, dann sollte man das nicht durch ein VisualBasic im Namespace verschleiern.
Die Untersützung ist nicht oder wenig nützlich oder aber umständlich: Kann ich nicht beurteilen.
Die Unterstützung ist unbekannt: so war das bei mir. Vermutlich ist sie bei C#-Programmierer generell deutlich weniger bekannt als bei VB-Programmieren.
laut Doku befindet sich diese Klasse in der Assembly Microsoft.VisualBasic. Da ist sie aber nicht drin?! Wollte mir das Ding mal mittels Reflector anschauen. Ich referenziere auf "Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac". Liegt die doch woanders?
"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)
... Application.Run für das Splash aufrufen. ... Anschließend im Haupt-Thread ein zweites Application.Run für das eigentliche (Haupt-)Form...
Ich denke jedes Application.Run erzeugt einen neuen GUI-Thread. Dann würde ich hier ja wieder 2 GUI-Threads haben. Habe ich das falsch verstanden mit dem Application.Run?
Nach meinem Wissensstand wären das dann insgesamt 3 Threads:
- ein Thread wird sowieso vom Framework für jede Applikation berietgestellt
- ein GUI-Thread durch Application.Run für den Splash
- ein GUI-Thread durch Application.Run für das Hauptform
Komisch. Nehme ich die MS.VB Assembly aus dem GAC, ist da fast nichts drin. Nehme ich die direkt aus dem Frameworkordner aus dem Windowsordner, ist alles drin. Naja, jetzt hab ichs jedenfalls.
Danke.
"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)
Ich denke jedes Application.Run erzeugt einen neuen GUI-Thread.
nein, beide Application.Run würden ja - nacheinander - im selben Thread ausgeführt. Meinem Vorschlag folgend im Haupt-Thread. Application.Run erzeugt selbst keinen (weiteren/neuen) Thread, sondern führt alle Aktionen in dem Thread aus, in dem es aufgerufen wurde.
Zitat
Habe ich das falsch verstanden mit dem Application.Run?
Anscheinend.
Hallo Atomroflman,
Zitat
Du brauchst keinen neuen Thread aufzumachen...
Ausser du willst im Hintergrund noch irgendwelche Sachen laden...
für das reine Ein-/Ausblenden hättest du recht, aber es geht hier doch um langwierige Initialisierungen, die dann natürlich in einen extra Thread ausgelagert werden müssen.
@herbivore :
Die geschichte hinter WindowsFormsApplicationBase ist, das es schon in der IDE
bei VB.NET Projekten direkt erreichbar ist, und dann von VS direkt als die startklasse
erstellt wird.
Das hat überhaupt nichts mit VB Compatibility oder ähnlichem zu tun.
Genausowenig wie die BigInter klassen im J#.