I have Windows Form project that turns one format of csv file into another. I am trying to show the converting progress while converting. Converting method throws an exception if converting fails. When converting fails, I close ConvertingScreen but when I close ConvertingScreen System.InvalidOperationException occurs.
invoke or begininvoke cannot be called on a control until the window handle has been created
It seems it never happens if I add some waits before I close. I have tried checking HandleCreated but it didnt go well. I used to do this kind of jobs by adding only visible label while it is on progress. This is my first time doing such like this way. Is this bad practice? If not how can I fix this? Below is simple code that can describe everything what is happening to me.
// MainForm
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
ConvertingScreen.ShowScreen();
// Converts here and results in failure so throwing an exception
throw new NotImplementedException();
}
catch (Exception)
{
ConvertingScreen.CloseForm();
MessageBox.Show("error");
}
}
}
// ConvertingScreen
public class ConvertingScreen : Form
{
public ConvertingScreen()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
// label1
this.label1.Font = new System.Drawing.Font("MS UI Gothic", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128)));
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(316, 22);
this.label1.TabIndex = 0;
this.label1.Text = "";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
// ConvertingScreen
this.BackColor = System.Drawing.Color.LightGray;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.ClientSize = new System.Drawing.Size(340, 40);
this.ControlBox = false;
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(340, 40);
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(340, 40);
this.Name = "ConvertingScreen";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "ConvertingScreen";
this.TopMost = true;
this.ResumeLayout(false);
}
private Label label1;
private delegate void CloseDelegate();
private delegate void UpdateTextDelegate(string text);
private static ConvertingScreen form;
public static void ShowScreen()
{
if (form != null) return;
form = new ConvertingScreen();
Thread thread = new Thread(new ThreadStart(ConvertingScreen.ShowForm));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
private static void ShowForm()
{
if (form != null) Application.Run(form);
}
public static void CloseForm()
{
form?.Invoke(new CloseDelegate(ConvertingScreen.CloseFormInternal));
}
private static void CloseFormInternal()
{
if (form != null)
{
form.Close();
form = null;
}
}
public static void Update(string text)
{
if (form != null) form.UpdateLabel(text);
}
private void UpdateLabel(string text)
{
if (InvokeRequired)
{
this.Invoke(new UpdateTextDelegate(UpdateLabel), new object[] { text });
return;
}
label1.Text = text;
}
}