Я оптимизирую запуск приложения WinForms. Одной проблемой, которую я определил, является загрузка формы экрана-заставки. Это берет о половине секунды к секунде.
Я знаю, что многопоточность нет - нет на частях UI, однако, видя, как экран-заставка является довольно автономной частью приложения, это возможный так или иначе смягчить его производительность, пораженную путем броска его один некоторый другой поток (возможно, в способе, которым Chrome делает это), так, чтобы важные части приложения могли на самом деле начаться.
.NET framework уже имеет очень хорошую поддержку экранов-заставок в приложениях Windows Forms. Посмотрите в этой ветке образец кода. Он действительно оптимизирован для горячего запуска, он обеспечивает запуск и работу заставки и экрана перед инициализацией основного приложения.
Нет никакой пользы от создания потока, если ваша цель - как можно быстрее поднять заставку.
Есть несколько способов создания заставок, и более сложный из них упомянут здесь , но это простой метод, который я использовал с полным успехом:
Просто убедитесь, что вы загрузили и показали сначала заполните форму , а затем продолжайте загружать приложение, пока пользователь смотрит на красивый экран-заставку. Когда основная форма завершает загрузку, она может закрыть заставку прямо перед тем, как она покажет себя (простой способ сделать это - передать форму заставки в основную форму в ее конструкторе):
static void Main()
{
Application.SetCompatibleTextRenderingDefault(false);
SplashForm splash = new SplashForm();
splash.Show();
splash.Refresh(); // make sure the splash draws itself properly
Application.EnableVisualStyles();
Application.Run(new MainForm(splash));
}
public partial class MainForm : Form
{
SplashForm _splash;
public MainForm(SplashForm splash)
{
_splash = splash;
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// or do all expensive loading here (or in the constructor if you prefer)
_splash.Close();
}
}
Альтернатива: если вы предпочитаете не передавать заставку в MainForm (возможно, это кажется неэлегантным), затем подпишитесь на событие Load MainForm и закройте там экран-заставку:
static class Program
{
static SplashForm _splash;
[STAThread]
static void Main()
{
Application.SetCompatibleTextRenderingDefault(false);
_splash = new SplashForm();
_splash.Show();
_splash.Refresh();
Application.EnableVisualStyles();
MainForm mainForm = new MainForm();
mainForm.Load += new EventHandler(mainForm_Load);
Application.Run(mainForm);
}
static void mainForm_Load(object sender, EventArgs e)
{
_splash.Dispose();
}
}
Как упоминалось в this thread , потенциальным недостатком этого решения является то, что пользователь не сможет взаимодействовать с заставкой. Однако обычно этого не требуется.
Многопоточность в WinForms - это нормально, пока весь пользовательский интерфейс находится в одном потоке.
Именно так обычно и делают заставки. Важная работа выполняется в фоновом потоке, в то время как окно-заставка отображается в потоке пользовательского интерфейса, чтобы пользователь знал, что остальная часть программы появится в ближайшее время.
После того, как произошло важное событие, вызовите событие, чтобы поток пользовательского интерфейса знал, что пора скрыть экран-заставку (просто не забудьте маршалировать обработчик событий, используя Invoke (), обратно в поток пользовательского интерфейса, чтобы закройте заставку).
Да.
Вам необходимо создать новый поток STA, который показывает экран-заставку, используя Application.Run
, затем вызовите Close
, используя Invoke
, после того, как основная форма будет готова. (в основном потоке).
ИЗМЕНИТЬ : Например:
static SplashForm splash;
Thread splashThread = new Thread(delegate() {
splash = new SplashForm();
Application.Run(splash); //Blocking call on separate thread
});
splashThread.SetApartmentState(ApartmentState.STA)
splashThread.Start();
LoadApp();
//In MainForm_Shown:
splash.BeginInvoke(new Action(splash.Close));
Для оптимальной производительности вы должны сделать так, чтобы ваш метод Main
отображал экран-заставку, а затем вызвал отдельный метод, загружающий приложение. Таким образом, все сборки будут загружены после отображения экрана-заставки. (Когда вы вызываете метод, JITter загружает все используемые им типы до того, как метод начнет выполняться)
Ответ действительно о восприятии. Существуют различные методы, NGEN и сборка, помещающие вещи в GAC, но вы должны понимать, что происходит на самом деле.
C # требуется время для загрузки виртуальной машины, загрузки ссылочных сборок и загрузки сборок в зависимости от того, что находится на этом экране-заставке. И тогда для запуска первого экрана еще требуется некоторое время из "холодного" старта.
Это из-за JIT-компиляции, которая происходит при первом доступе к экрану.
Я использую традиционную легкую страницу-заставку, которая загружается быстро и становится видимой, но в фоновом режиме я создаю поток и загружаю невидимую форму. В этой форме есть все элементы управления, которые я намереваюсь использовать, поэтому JIT-компилятор делает свое дело и загружает сборки. Это создает иллюзию отзывчивости с легкостью. Время, необходимое для запуска + видимой страницы-заставки + паузы + времени, чтобы щелкнуть 1-й вариант, больше, чем время, необходимое для выполнения потока, а затем очистки и выгрузки формы.
В противном случае приложения кажутся неуклюжими и медленными для пользователей при первом запуске. Горячий запуск экранов происходит намного быстрее, потому что сборка и JIT завершены.