У меня есть приложение, предназначенное для работы в сети. Это означает, что первоначальный запуск этого приложения может занять некоторое время. Поэтому я собрал заставку, чтобы немного улучшить процесс.
Он использует многопоточность для отображения формы статическим методом. Я все еще новичок в потоке, поэтому, когда я получал ошибки, я был немного озадачен тем, что и почему.
Оказывается, мой код прекрасно работает, когда я запускаю его вне отладчика Visual Studio. Но когда я запускаю его из отладчика, я получаю исключение:
"Операция с несколькими потоками недопустима: доступ к элементу управления 'выполняется из потока, отличного от потока, в котором он был создан."
Вот мой класс:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace MyApp
{
public partial class SplashScreen : Form
{
private static double OPACITY_INCREMENT = .05;
private static SplashScreen _splashForm;
private static SplashScreen SplashForm
{
get { return SplashScreen._splashForm; }
set { SplashScreen._splashForm = value; }
}
private static void ShowForm()
{
SplashScreen.SplashForm = new SplashScreen();
Application.Run(SplashScreen.SplashForm);
}
internal static void CloseForm()
{
if (SplashScreen.SplashForm != null &&
SplashScreen.SplashForm.IsDisposed == false)
{
// Make it start going away.
OPACITY_INCREMENT = -OPACITY_INCREMENT;
}
SplashScreen.SplashThread = null;
SplashScreen.SplashForm = null;
}
private static Thread _splashThread;
private static Thread SplashThread
{
get { return SplashScreen._splashThread; }
set { SplashScreen._splashThread = value; }
}
internal static void ShowSplashScreen()
{
if (SplashScreen.SplashForm != null)
{
return;
}
SplashScreen.SplashThread = new Thread(new ThreadStart(SplashScreen.ShowForm));
SplashScreen.SplashThread.IsBackground = true;
SplashScreen.SplashThread.SetApartmentState(ApartmentState.STA);
SplashScreen.SplashThread.Start();
}
public SplashScreen()
{
InitializeComponent();
this.timerFade.Start();
this.ClientSize = this.BackgroundImage.Size;
}
private void SplashScreen_Load(object sender, EventArgs e)
{
}
private void timerFade_Tick(object sender, EventArgs e)
{
if (OPACITY_INCREMENT > 0)
{
if (this.Opacity < 1)
this.Opacity += OPACITY_INCREMENT;
}
else
{
if (this.Opacity > 0)
this.Opacity += OPACITY_INCREMENT;
else
{
this.Invoke(new MethodInvoker(this.TryClose));
}
}
}
private void TryClose()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(this.TryClose));
}
this.Close();
}
}
}
Я вызываю заставку из метода Program.cs Main.
namespace CIMA
{
static class Program
{
// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SplashScreen.ShowSplashScreen();
// Code omitted for brevity.
SplashScreen.CloseForm();
// Code omitted for brevity.
}
}
}
Я хотел бы иметь возможность вызывать SplashScreen.CloseForm () из одной из моих других форм, но я еще не настолько пробовал это сделать. Я не понимаю, что задумал отладчик.
Я что-то упустил? Или мне нужно отключить заставку, если она запускается в отладчике?
Если это так, какой хороший способ сделать это? Я хочу избегать использования символов компиляции, если это возможно, потому что я ненавижу их отслеживать.