Многопоточный экран-заставка в C #? - PullRequest
60 голосов
/ 08 сентября 2008

Я хочу, чтобы во время загрузки приложения отображался заставочный экран. У меня есть форма с привязкой к панели управления системой. Я хочу, чтобы заставка отображалась во время загрузки этой формы, что занимает некоторое время, так как он получает доступ к API веб-службы для заполнения некоторых раскрывающихся списков. Я также хочу провести некоторое базовое тестирование зависимостей перед загрузкой (то есть веб-сервис доступен, файл конфигурации доступен для чтения). По мере прохождения каждой фазы запуска я хочу обновлять заставку с прогрессом.

Я много читал о потоках, но заблудился о том, откуда это следует контролировать (метод main()?). Мне также не хватает как Application.Run() работает, это где темы для этого должны быть созданы? Теперь, если форма с управлением в системном трее является «живой» формой, должен ли всплеск исходить оттуда? Разве он не загрузится, пока форма не будет заполнена в любом случае?

Я не ищу раздаточный материал, скорее алгоритм / подход, чтобы я мог понять это раз и навсегда :)

Ответы [ 12 ]

2 голосов
/ 22 августа 2013

Я не согласен с другими ответами, рекомендующими WindowsFormsApplicationBase. По моему опыту, это может замедлить ваше приложение. Если быть точным, то пока он запускает конструктор вашей формы параллельно с заставкой, он откладывает событие Shown вашей формы.

Рассмотрим приложение (без заставки) с конструктором, который занимает 1 секунду, и обработчиком событий в Shown, который занимает 2 секунды. Это приложение можно использовать через 3 секунды.

Но предположим, что вы устанавливаете заставку, используя WindowsFormsApplicationBase. Вы можете подумать, что MinimumSplashScreenDisplayTime из 3 секунд разумно и не замедлит ваше приложение. Но попробуйте, ваше приложение теперь будет загружаться за 5 секунд.


class App : WindowsFormsApplicationBase
{
    protected override void OnCreateSplashScreen()
    {
        this.MinimumSplashScreenDisplayTime = 3000; // milliseconds
        this.SplashScreen = new Splash();
    }

    protected override void OnCreateMainForm()
    {
        this.MainForm = new Form1();
    }
}

и

public Form1()
{
    InitializeComponent();
    Shown += Form1_Shown;
    Thread.Sleep(TimeSpan.FromSeconds(1));
}

void Form1_Shown(object sender, EventArgs e)
{
    Thread.Sleep(TimeSpan.FromSeconds(2));
    Program.watch.Stop();
    this.textBox1.Text = Program.watch.ElapsedMilliseconds.ToString();
}

Вывод: не используйте WindowsFormsApplicationBase, если в вашем приложении есть обработчик события Slown. Вы можете написать лучший код, который запускает всплеск параллельно как конструктору, так и событию Shown.

0 голосов
/ 04 сентября 2017

На самом деле многопоточность здесь не нужна.

Пусть ваша бизнес-логика генерирует событие всякий раз, когда вы хотите обновить заставку.

Затем пусть ваша форма обновит заставку соответствующим образом в методе, подключенном к обработчику событий.

Чтобы различать обновления, вы можете запускать различные события или предоставлять данные в классе, унаследованном от EventArgs.

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

На самом деле с этим вы можете даже поддерживать, например, GIF-изображение в виде заставки. Чтобы это работало, вызовите Application.DoEvents () в вашем обработчике:

private void SomethingChanged(object sender, MyEventArgs e)
{
    formSplash.Update(e);
    Application.DoEvents(); //this will update any animation
}
...