У меня есть приложение на C # .NET Framework 4.7, в котором загрузка основной формы занимает некоторое время (запросы к базе данных и т. Д.).
Чтобы сообщить пользователю, что приложение запущено и загружается, яЯ реализовал заставку.
Однако мне не удалось заставить работать инициализацию MainForm (запросы к базе данных и т. д.).
Если я поместил код инициализации в конструктор MainForm,и поместив mainForm = new MainForm()
в основной поток / задачу, заставка зависает, поскольку DoEvent () не работает, поскольку работа выполняется синхронно.
Если я помещаю код инициализации в метод MainForm и помещаю mainForm = new MainForm()
как показано ниже, и поместите инициализацию, как показано ниже, я получу InvalidOperationException
s при попытке доступа к компонентам, находящимся в другом потоке / задаче.
Когда я пытаюсь обойти это исключение, используяInvoke
в задаче (как показано ниже) я получаю еще одну InvalidOperationException
жалобу на Invoke
, которая не может быть вызвана, когда форма не отображается (дескриптор окна)е не создано).Я пытался создать дескриптор окна перед тем, как вызвать Invoke
, но получил то же исключение, поскольку для Invoke
чего-либо нужно показать форму.
Как инициализировать MainForm в отдельном потоке / задачетак что несколько задач инициализации могут выполняться параллельно в функции Main?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
internal static class Program
{
[STAThread]
private static int Main()
{
// Display the splash screen.
var splashScreen = new SplashScreenForm()
{
ApplicationTitle = Program.Information.EntryAssembly.Title,
ApplicationVersionInformation = string.Format("Version {0} ({1})", Program.Information.EntryAssembly.InformationalVersion, Program.Information.EntryAssembly.Configuration),
Copyright = Program.Information.EntryAssembly.Copyright
};
splashScreen.Show();
var initTasks = new List<Task>();
var mainForm = new MainForm();
// Load main form.
{
var initTask = new Task(() => { mainForm.Initialize(); });
initTasks.Add(initTask);
initTask.Start();
}
// Some other initialization tasks, that are NOT related to MainForm.
{
var initTask = new Task(() => { Console.WriteLine("Foo Bar") });
initTasks.Add(initTask);
initTask.Start();
}
// Wait until all initialization tasks are done.
while (initTasks.Any((Task t) => { return !Convert.ToBoolean(t.IsCanceled | t.IsFaulted | t.IsCompleted); }))
{
Thread.Sleep(10);
Application.DoEvents();
}
// Check for failed initialization tasks.
if (initTasks.Any((Task t) => { return Convert.ToBoolean(t.IsCanceled | t.IsFaulted); }))
{
var exes = new List<Exception>();
foreach (var t in initTasks.FindAll((Task t) => { return Convert.ToBoolean(t.IsCanceled | t.IsFaulted); }))
{
exes.Add(t.Exception);
}
throw new AggregateException("Some main initialization tasks have failed.", exes.ToArray());
}
// Cleanup tasks.
initTasks.ForEach((Task t) => { t.Dispose(); });
initTasks.Clear();
splashScreen.Close();
splashScreen.Dispose();
Application.Run(mainForm);
Application.Exit();
Application.DoEvents();
return 0;
}
}