Создание заставки - PullRequest
       28

Создание заставки

4 голосов
/ 13 августа 2010

Концепция заставки не кажется мне чем-то настолько сложным, но у меня возникают проблемы с окрашиванием всего заставки.

Допустим, у меня есть два System.Windows.Forms.Form с: RealForm и SplashScreen. RealForm содержит начальный графический интерфейс. В процессе загрузки RealForm (то есть в обработчике события Load) RealForm создает соединение с базой данных, а затем проверяет соединение. Это может занять несколько секунд, поэтому, прежде чем я сделаю все это, я попытаюсь вызвать заставку примерно так:

private void RealForm_Load(object sender, EventArgs e)
{
    SplashScreen splash = new SplashScreen();
    splash.Show();
    loadAndCheckDatabase();
    splash.Close();
}

Проблема в том, что заставка только частично прорисована, и поэтому она не очень похожа на заставку. Есть идеи почему? Что мне делать?

Что касается бонусных баллов, кто-нибудь знает, где найти объяснение всех серий событий, которые происходят при типичном создании, использовании и уничтожении форм? Вышеупомянутая проблема, вероятно, связана с тем, что я не понимаю, в каком порядке происходят события и где можно подключиться к событиям формы.


UPDATE Близко, но не совсем: ищите немного больше советов. Вот текущий код:

private SplashScreen splash = new SplashScreen();

private void RealForm_Load(object sender, EventArgs e)
{

    splash.Show();

    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
         (worker_RunWorkerCompleted);
    worker.RunWorkerAsync();
    this.Visible = false;

}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    splash.Close();
    this.Visible = true;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    loadAndCheckDatabase();
}

К сожалению, this.Visible = false ничего не делает, потому что он автоматически устанавливается на true в коде, который я не контролирую. Итак, чтобы обойти это, я поместил this.Visible = false в обработчик для события Shown формы. Однако, как вы, вероятно, догадываетесь, вы все равно сможете увидеть форму за доли секунды ... так что это не очень хорошее решение.

Есть ли способ подождать в рабочем потоке, пока я все еще в обработчике загрузки?

Ответы [ 6 ]

9 голосов
/ 13 августа 2010

Вы отображаете заставку и проверяете свою базу данных в том же потоке. Нить может делать только одну вещь за один раз.

Быстрый и дешевый способ исправить это - периодически loadAndCheckDatabase() звонить Application.DoEvents(). Однако это дешевое решение.

Вы действительно хотите запустить loadAndCheckDatabase () в своем собственном потоке, BackgroundWorker - это хороший простой способ сделать это.

2 голосов
/ 12 февраля 2014

Как и я, вы, вероятно, создали это в качестве запоздалой мысли и не хотите проходить через весь процесс перестройки своего кода для соответствия многопоточной архитектуре ...

Сначала создайте новую форму с именем SpashScreen, в свойствах нажмите на BackgroundImage и импортируйте любое изображение, которое вы хотите. Также установите для FormBorderStyle значение Нет, чтобы вы не могли щелкнуть по значку x, чтобы закрыть экран.

    public Form1()
    {
        InitializeComponent();

        BackgroundWorker bw = new BackgroundWorker();
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerAsync();  // start up your spashscreen thread
        startMainForm();      // do all your time consuming stuff here  
        bw.CancelAsync();     // close your splashscreen thread  
    }


    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        SplashScreen ss = new SplashScreen();
        ss.Show();

        while (!worker.CancellationPending) //just hangout and wait
        {
            Thread.Sleep(1000);
        }

        if (worker.CancellationPending)
        {
            ss.Close();
            e.Cancel = true;
        }

    }

Это не поддерживает индикатор прогресса или какие-либо необычные вещи, но я уверен, что его можно настроить.

1 голос
/ 22 ноября 2013

Почему бы при запуске приложения не открыть форму, которая загружает все, что нужно для загрузки в класс, а затем, когда она завершит загрузку, открыть основную форму и отправить в нее класс?В качестве альтернативы вы можете использовать одиночный файл для загрузки всего.

В вашем Program.cs:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new SplashScreen());
    }

Затем в SplashScreen:

    public SplashScreen()
    {
        InitializeComponent();
        LoadEverything();
        this.Visible = false;
        MainForm mainForm = new MainForm(LoadedClass);
        mainForm.ShowDialog();
        this.Close();
    }

Мне нужнообновите это:

Вот рабочий код (выше только концепция).

    public SplashScreen()
    {
        InitializeComponent();
        _currentDispatcher = Dispatcher.CurrentDispatcher;

        // This is just for the example - start a background method here to call
        // the LoadMainForm rather than the timer elapsed
        System.Timers.Timer loadTimer = new System.Timers.Timer(2000);
        loadTimer.Elapsed += LoadTimerElapsed;
        loadTimer.Start();
    }

    public void LoadMainForm()
    {
        // Do your loading here
        MainForm mainForm = new MainForm();

        Visible = false;
        mainForm.ShowDialog();
        System.Timers.Timer closeTimer = new System.Timers.Timer(200);
        closeTimer.Elapsed += CloseTimerElapsed;

        closeTimer.Start();
    }

    private Dispatcher _currentDispatcher;

    private void CloseTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (sender is System.Timers.Timer && sender != null)
        {
            (sender as System.Timers.Timer).Stop();
            (sender as System.Timers.Timer).Dispose();
        }
        _currentDispatcher.BeginInvoke(new Action(() => Close()));
    }

    private void LoadTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (sender is System.Timers.Timer && sender != null)
        {
            (sender as System.Timers.Timer).Stop();
            (sender as System.Timers.Timer).Dispose();
        }
        _currentDispatcher.BeginInvoke(new Action(() => LoadMainForm()));
    }
1 голос
/ 13 августа 2010

Вы должны запустить заставку в другом потоке, что позволит ему правильно рисовать.

Посмотрите здесь:

http://www.codeproject.com/KB/cs/prettygoodsplashscreen.aspx

1 голос
/ 13 августа 2010

Попробуйте поместить вызов loadAndCheckDatabase в фоновом потоке, переместить туда закрытие заставки или просто закрыть его таймером на заставке.При работе в фоновом потоке все функции пользовательского интерфейса смогут работать без перебоев.

0 голосов
/ 06 июля 2013

Вы можете использовать команду await с .Net Framework 4.5 Ваша форма не будет видна, пока задача не будет завершена

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...