60 votes

Écran de démarrage multi-thread en C #?

Je veux un écran de démarrage pour afficher lorsque l'application est en cours de chargement. J'ai un formulaire avec un plateau de système de contrôle liés à elle. Je veux que l'écran de démarrage pour afficher cette forme de charges, ce qui prend un peu de temps puisque c'est l'accès à une API de service web pour remplir certains menus déroulants. J'ai aussi envie de faire quelques test de base pour les dépendances avant le chargement (qui est, le service web est disponible, le fichier de configuration est lisible). Comme chaque phase de démarrage va, je veux mettre à jour l'écran de démarrage avec le progrès.

J'ai lu beaucoup de choses sur les threads, mais je suis perdu sur ce doit être contrôlé à partir de (la méthode main ()?). Je suis également manquant comment Application.Run() fonctionne, est-ce là le fils pour ce qui devrait être créé à partir de? Maintenant, si la forme avec la barre d'état système de contrôle est le fait de "vivre" la forme, le splash venir de là? Ne serait-il pas de charge jusqu'à ce que le formulaire est complété, de toute façon?

Je ne suis pas à la recherche d'un code de document, plus d'un algorithme/approche donc, je peux le comprendre une fois pour toutes :)

46voto

Guy Starbuck Points 14241

Eh bien, pour une application ClickOnce que j'ai déployés dans le passé, nous avons utilisé Microsoft.VisualBasic espace de noms pour gérer l'écran de démarrage de filetage. Vous pouvez consulter et utiliser le Microsoft.VisualBasic assemblée à partir de C# dans .NET 2.0 et il offre beaucoup de plaisir dans les services.

  1. La principale forme d'hériter de Microsoft.VisualBasic.WindowsFormsApplicationBase
  2. Remplacer le "OnCreateSplashScreen" méthode comme suit:

    protected override void OnCreateSplashScreen()
    {
        this.SplashScreen = new SplashForm();
        this.SplashScreen.TopMost = true;
    }
    

Très simple, il montre votre SplashForm (dont vous avez besoin pour créer), tandis que le chargement est en cours, puis il se ferme automatiquement une fois que le formulaire principal le chargement est terminé.

Ce qui fait vraiment les choses simples, et le VisualBasic.WindowsFormsApplicationBase est bien sûr testé par Microsoft et a beaucoup de fonctionnalités qui peuvent rendre votre vie beaucoup plus facile dans les Winforms, même dans une application 100% C#.

À la fin de la journée, c'est tous les IL et le bytecode de toute façon, alors pourquoi ne pas l'utiliser?

46voto

aku Points 54867

L'astuce consiste à créer de thread distinct chargé de l'écran de démarrage de l'affichage.
Lorsque vous exécutez votre application .net crée le thread principal et des charges spécifié (principale) de forme. Pour dissimuler le travail dur, vous pouvez masquer le formulaire principal jusqu'à ce que le chargement est terminé.

En supposant que Form1 - est votre principale forme et SplashForm est de haut niveau, borderles splash nice formulaire:

private void Form1_Load(object sender, EventArgs e)
{
    Hide();
    bool done = false;
    ThreadPool.QueueUserWorkItem((x) =>
    {
        using (var splashForm = new SplashForm())
        {
            splashForm.Show();
            while (!done)
                Application.DoEvents();
            splashForm.Close();
        }
    });

    Thread.Sleep(3000); // Emulate hardwork
    done = true;
    Show();
}

14voto

Adam Nofsinger Points 1680

Après tout Google et DONC, pour les solutions, c'est mon préféré: http://bytes.com/topic/c-sharp/answers/277446-winform-startup-splash-screen

FormSplash.cs:

public partial class FormSplash : Form
{
    private static Thread _splashThread;
    private static FormSplash _splashForm;

    public FormSplash() {
        InitializeComponent();
    }

    /// <summary>
    /// Show the Splash Screen (Loading...)
    /// </summary>
    public static void ShowSplash()
    {
        if (_splashThread == null)
        {
            // show the form in a new thread
            _splashThread = new Thread(new ThreadStart(DoShowSplash));
            _splashThread.IsBackground = true;
            _splashThread.Start();
        }
    }

    // called by the thread
    private static void DoShowSplash()
    {
        if (_splashForm == null)
            _splashForm = new FormSplash();

        // create a new message pump on this thread (started from ShowSplash)
        Application.Run(_splashForm);
    }

    /// <summary>
    /// Close the splash (Loading...) screen
    /// </summary>
    public static void CloseSplash()
    {
        // need to call on the thread that launched this splash
        if (_splashForm.InvokeRequired)
            _splashForm.Invoke(new MethodInvoker(CloseSplash));

        else
            Application.ExitThread();
    }
}

Programme.cs:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // splash screen, which is terminated in FormMain
        FormSplash.ShowSplash();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        // this is probably where your heavy lifting is:
        Application.Run(new FormMain());
    }
}

FormMain.cs

    ...

    public FormMain()
    {
        InitializeComponent();            

        // bunch of database access, form loading, etc
        // this is where you could do the heavy lifting of "loading" the app
        PullDataFromDatabase();
        DoLoadingWork();            

        // ready to go, now close the splash
        FormSplash.CloseSplash();
    }

J'ai eu des problèmes avec l' Microsoft.VisualBasic solution -- Travaillé trouver sur XP, mais sur Windows 2003 Serveur Terminal server, l'application principale formulaire de présentation (après l'écran de démarrage) dans le fond, et la barre des tâches clignote. Et apporter un au premier plan la fenêtre de discussion dans le code est une toute autre boîte de pandore que vous pouvez Google/DONC pour.

10voto

Jay Points 27907

C'est une vieille question, mais j'ai tenu à venir à travers elle, en essayant de trouver une tige filetée de l'écran de démarrage solution pour WPF qui pourrait inclure de l'animation.

Voici ce que j'ai finalement reconstitué:

App.XAML:

<Application Startup="ApplicationStart" …

App.XAML.cs:

void ApplicationStart(object sender, StartupEventArgs e)
{
        var thread = new Thread(() =>
        {
            Dispatcher.CurrentDispatcher.BeginInvoke ((Action)(() => new MySplashForm().Show()));
            Dispatcher.Run();
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = true;
        thread.Start();

        // call synchronous configuration process
        // and declare/get reference to "main form"

        thread.Abort();

        mainForm.Show();
        mainForm.Activate();
  }

9voto

DelftRed Points 116

Je vous recommandons de téléphoner Activate(); directement après le dernier Show(); dans la réponse fournie par aku.

Citant MSDN:

Activation d'un formulaire qu'elle apporte à l' avant, si c'est l'active l'application, ou il clignote la fenêtre légende si ce n'est pas l'actif application. Le formulaire doit être visible pour cette méthode pour avoir un quelconque effet.

Si vous n'activez pas votre formulaire principal, il peut être affiché derrière toutes les autres fenêtres ouvertes, rendant l'air un peu idiot.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X