2

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;
    }
}
  • Why are you throwing `throw new NotImplementedException();`? –  Mar 12 '21 at 02:04
  • As I added comments in the code, when converting fails it is going to throw an exception. So I am just throwing any exception to perform as like converting has been failed. – グジョンミン Mar 12 '21 at 02:10
  • Delay the processing that could lead to the attempt to call `Invoke()` until you are sure that the window's handle has been created, i.e. the `Load` or `Shown` event has been raised. See duplicate. Note: I do not recommend using the `CreateControl()` method to force the handle to be created; just handle the event you prefer and let the framework do its thing when it wants to. – Peter Duniho Mar 12 '21 at 02:12
  • See also https://stackoverflow.com/questions/397121/load-vs-shown-events-in-windows-forms – Peter Duniho Mar 12 '21 at 02:12
  • I have read those and tried before I make a question. None of those works. – グジョンミン Mar 12 '21 at 04:21

0 Answers0