2012-11-03 5 views
9

C# WPF ApplicationSplashScreen.Close (Timespan.FromMilliseconds (int)): Esiste un evento inviato in Scadenza completata?

Ho un SplashScreen viene visualizzata all'avvio per un importo minimo di tempo utilizzando

Thread.Sleep(int); //int = milliseconds to display splash screen 

Una volta raggiunto quel tempo il sonno, il codice riprende e la SplashScreen sfuma di chiudere entro utilizzando

SplashScreen.Close(Timespan.FromMilliseconds(int)); //int = milliseconds fade-out 

desidero pausa a questo punto per attendere l'SplashScreen è diventata trasparente 100% ed è completamente chiusa, quindi continuare con altri compiti, IE Scrittura sulla console o visualizzazione di una finestra principale.

C'è un evento attivato quando (TimeSpan.FromMilliseconds (int)) è completo? Qualche altro suggerimento?

namespace StartupSplash 
{ 
    public class SplashScreenStartup 
    { 
     //IMPORTANT:set image property to Resource and NOT Splash Screen 
     private SplashScreen Splash = new SplashScreen("Resources/SplashScreen.png"); 

     public void SplashScreenStartUp() 
     { 
      Splash.Show(false, true); 
      Thread.Sleep(3000); // Pause code, display splash screen 3 seconds 
      Splash.Close(TimeSpan.FromMilliseconds(3000)); // 3 second splash fade-out 
      // I want to wait until splash screen fadeOut has completed before 
      // this next console output is performed. 
      Console.WriteLine("Executes before Splash fadeOut completes."); 
     } 

    } 
+1

Presumo che questo sia WPF? –

+0

Sì, lo è.Grazie per averlo indicato. – reido113

+2

Perché non lo fai all'interno di un thread e aspetta solo che il thread finisca, dovrebbe darti i risultati che vuoi e semplicemente implementarlo. –

risposta

0

Non ho mai trovato un evento da ascoltare al completamento di TimeSpan. Inoltre, dopo aver deciso di non interrompere i thread, ho scelto di utilizzare DispatcherTimers.

(ho assottigliato e conteneva la logica in questa classe per scopi di riferimento)

using System; 
using System.Windows; 
using System.Windows.Threading; 


namespace StartupSplash2 
{ 

public partial class MainWindow : Window 
{ 
    private DispatcherTimer visibleTimer; 
    private DispatcherTimer fadeoutTimer; 
    private SplashScreen splash; 
    private int visibleTime = (4000); //milliseconds of splash visible time 
    private int fadeoutTime = (1500); //milliseconds of splash fadeout time 

    public MainWindow() 
    { 
     //hide this MainWindow window until splash completes 
     this.Visibility = Visibility.Hidden; 
     InitializeComponent(); 
     splashIn(); //start the splash 
    } 

    private void splashIn() 
    { 
     splash = new SplashScreen("Resources/SplashScreen.png"); //ensure image property is set to Resource and not screen saver 
     visibleTimer = new DispatcherTimer(); //timer controlling how long splash is visible 
     visibleTimer.Interval = TimeSpan.FromMilliseconds(visibleTime); 
     visibleTimer.Tick += showTimer_Tick; //when timer time is reached, call 'showTimer_Tick" to begin fadeout 
     splash.Show(false, true); //display splash 
     visibleTimer.Start(); 
    } 

    private void showTimer_Tick(object sender, EventArgs e) 
    { 
     visibleTimer.Stop(); 
     visibleTimer = null; //clear the unused timer 
     fadeoutTimer = new DispatcherTimer(); 
     fadeoutTimer.Interval = TimeSpan.FromMilliseconds(fadeoutTime); //a timer that runs while splash fades out and controlls when main window is displayed 
     fadeoutTimer.Tick += fadeTimer_Tick; //when fadeout timer is reached, call 'fadeTimer_Tick' to show main window 
     splash.Close(TimeSpan.FromMilliseconds(fadeoutTime)); //begin splash fadeout to close 
     fadeoutTimer.Start(); 
    } 

    private void fadeTimer_Tick(object sender, EventArgs e) 
    { 
     fadeoutTimer.Stop(); 
     fadeoutTimer = null; //clear the unused timer 
     splash = null; //clear the splash var 
     MainWindowReady(); //call method to display main window 
    } 

    public void MainWindowReady() 
    { 
     this.Visibility = Visibility.Visible; 
     //Here is the start of the Main Window Code 
     this.Content = "Ok, the app is ready to roll"; 
    } 

    } 
} 
3

Forse questo codice può essere d'aiuto. Uso della classe BackgroundWorker:

BackgroundWorker worker = new BackgroundWorker(); 
worker.DoWork += (o, ea) => 
{ 
    // Dispatcher.Invoke commands the dispatcher to do something 
    Dispatcher.Invoke((Action)(() => Splash.Close(TimeSpan.FromMilliseconds(3000))); 
    // Sleeps this worker but NOT the UI 
    Thread.Sleep(3000); 
}; 
worker.RunWorkerCompleted += (o, ea) => 
{ 
    // Open your mainwindow sample 
    MainWindow w = new MainWindow(); 
    w.Show(); 
}; 

//Runs the worker on its own thread 
worker.RunWorkerAsync(); 

Questo dovrebbe avviare la chiusura della vostra splashscreen, poi dormire attraverso di essa, e quando è fatto si aprirà il tuo MainWindow. In realtà uso qualcosa di molto simile a questo per implementare un login e informazioni di recupero per la mia app WPF, visualizzando una barra di avanzamento e aggiornando il testo al suo interno per cose come "Connessione al server", "Accesso" e "Recupero dati".

+0

Grazie per questa direzione. All'inizio ho avuto alcuni errori perché le parentesi ondulate che terminano .DoWork e .RunWorkerCompleted avevano bisogno di un punto e virgola dopo di loro. Tuttavia, ricevevo errori relativi a Dispatcher.Invoke. Durante il tentativo di risolvere il problema ho trovato il seguente codice per funzionare. – reido113

+0

Oh naturalmente, mi dispiace! il tuo errore: il dispatcher perde una parentesi alla fine. Informazioni sullo sfondo: ho scoperto che puoi semplicemente inserire il tuo codice e vedere come va. Se fare qualcosa dà una spaccatura o qualcosa del genere, usa un'azione di dispatcher.invoke. Se ricevi qualcosa (come int fadeOutTime) e ottieni un errore, vedi se puoi usare un membro statico. È abbastanza semplice e mi piace molto la lezione. Non c'è niente di strano con i thread di avvio e di blocco, questo dovrebbe essere fatto solo se vuoi prestazioni ottimali, come con Battlefield 3 o qualcosa del genere. Non per mostrare un SS. – AmazingDreams

1

Ho trovato che il seguente codice funziona. Non sono del tutto chiaro perché e approfondirò per capirlo meglio.

Per cortesia, se necessario, sono qui per imparare e condividere. Saluti.

class Tester 
    { 
    // Create splash screen instance and reference the image location. 
    // IMPORTANT Ensure that the image properties are set to Resource and NOT Splash Screen 
    private SplashScreen Splash = new SplashScreen("Resources/SplashScreen.png"); 

    public void Display() 
    { 
     Splash.Show(false, true); 
     // pause the code, thus, displaying the splash for 3 seconds 
     Thread.Sleep(3000); 
     // close the splash 
     Close(); 
    } 

    private void Close() 
    { 
     // sets the fadeout time in milliseconds 
     int fadeOutTime = 1500; 

     // wait until the splash screen fadeOut has completed before writing to the console 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.DoWork += (o, ea) => 
     { 
      // Run background task (fade out and close the splash) 
      Splash.Close(TimeSpan.FromMilliseconds(fadeOutTime)); 
      // Sleep this worker but NOT the UI (for the same time as the fade out time) 
      Thread.Sleep(fadeOutTime); 
     }; 
     worker.RunWorkerCompleted += (o, ea) => 
     { 
      // Execute task after splash has closed completely 
      Console.WriteLine("This is after the splash screen fadeOut completes."); 
     }; 
     // start the background task, on it's own thread 
     worker.RunWorkerAsync(); 
    } 

} 
+2

Ummm ... Visualizzo solo una schermata iniziale quando l'inizializzazione della mia applicazione richiede così tanto tempo che l'utente potrebbe assumere che non ha fatto clic sul collegamento in modo corretto, e quindi fare nuovamente clic, avviando contemporaneamente due istanze dell'applicazione (che entrambi quindi richiedono più del doppio per l'avvio) ... quindi ... Consiglio vivamente di trovare un modo per NON dormire il thread principale mentre è visualizzata la schermata iniziale, in modo che possa avviare la tua app .. e se il modulo principale carica e visualizza DIETRO la schermata iniziale (suggerimento: sempre in alto), qual è il danno? Saluti. Keith. – corlettk

+0

Ottimi punti Keith. Grazie per questi suggerimenti. Lo migliorerò man mano che riesco a capire meglio su BackgroundWorker e il multithreading. Acclamazione Mate. Reid – reido113

+0

La mia idea di base è spostare TUTTO ciò che fa SplashScreen nel metodo DoWork ... in modo che sia mostrato, messo in pausa e sfumato tutto nel thread in background ... quindi è solo una chiamata al metodo nel tuo evento FormLoaded principale gestore di ShowSplashScreenInTheBackground ... ma sono bloccato a farlo vedere in quel modo ... sigh! – corlettk

0

alla fine ho venuto a conclusione che mi è stato abbaiare contro l'albero sbagliato nei miei commenti precedenti. La visualizzazione dello SplashScreen sullo sfondo è sia problematica (si è rifiutata di chiudersi automaticamente, indipendentemente da quello che ho provato), ma anche non disponibile. Ecco cosa ho finito con ... Davvero semplice!

using System; 
using System.Net; 
using System.Windows; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
    public Window1() { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) { 
     // show the splash screen 
     // nb: Resources/SplashScreenImage.png file Properties ~ Build Action='Resource' 
     var splashScreen = new SplashScreen("Resources/SplashScreenImage.png"); 
     splashScreen.Show(false); // don't close automatically 
     // ... initialise my application ... 
     Initialise(); 
     // close the splash screen. 
     splashScreen.Close(TimeSpan.FromMilliseconds(250D)); 
    } 

    private void Initialise() { 
     // do my long-running application initialisation on the main thread. 
     // In reality you'd do this download asyncronously, but in this case 
     // it serves as a simple proxy for some "heavy" inititalisation work. 
     textBox1.Text = new WebClient().DownloadString("http://stackoverflow.com/questions/13213625/splashscreen-closetimespan-frommilliseconds-listen-for-closed-event"); 
    } 
    } 

} 

Mi auguro che aiuta ... anche se non sono del tutto sicuro che sarà ;-)

Cin cin. Keith.

PS: Mi chiedo perché lo splash ha rifiutato di chiudere? A mio avviso, internamente si basa su eventi che sono disponibili solo (cioè abbonabili) sull'equivalente di WPF del thread di invio-evento (qualunque sia il suo nome).

+0

Inizialmente, ho pensato che si sarebbe verificato un evento al completamento di TimeSpan. Nel tentativo di evitare l'interruzione di Thread, ho iniziato a perseguire l'uso dei timer per questo. Riceverò un codice di soluzione non appena torno in pista. Che apprendimento mi ha portato avanti. :) – reido113

0

ho trovato un evento chiamato SplashScreen.Dismissed che consente di avviare l'applicazione dopo lo SplashScreen scadenza. Tuttavia, il sistema operativo minimo richiesto è Windows 8 e non potrei usarlo. Ulteriori informazioni possono essere trovate qui MSDN

Problemi correlati