I also had an idea of  doing some work in a thread - and while this hard job
was carried out... the main-gui-form should be modified, so the user will
spot a progress.
Did some lookup and went into "delegates", "eventhandlers", and "very advanced pieces of code".
It took me some time to fix, and I came up with this very simple example. Have a look.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ProcessingUI
// You will find a form with "button1": will do some work in a seperate thread, and
//   therefore you are allowed to do action in main-gui-form while this work is done, 
//   due to async. operation.
//   While work is done in seperate thread - the main-gui-form will have a label modified... 
//   having the steps: 1,2,3,0.
// Also found... "button2": will do some work in same thread as gui, and
//   therefore you are not allowed to do action in main-gui-form while this work is done,
//   due to sync. operation (only one thread is established).
//   While work is done in one-and-only-thread - the main-gui-form will have a label modified... 
//   having the steps: 1,2,3,0.
{
    public delegate void UpdateTextDelegate();
    public partial class Form1 : Form
    {
        public delegate void SetStatusText(string statusText);
        public SetStatusText mySetStatusTextDelegate;
        public Form1()
        {
            InitializeComponent();
            mySetStatusTextDelegate = new SetStatusText(SetStatusTextMethod);
        }
        private void button1_Click(object sender, EventArgs e)   // do work from new thread.
        {
            Worker w = new Worker(this);
            Thread thread1 = new Thread(new ThreadStart(w.DoWork));
            thread1.Start();
        }
        private void button2_Click(object sender, EventArgs e)   // do work from local class - form is locked during 1-3 steps.
        {
            SetStatusTextMethod("1");
            Thread.Sleep(3000);
            SetStatusTextMethod("2");
            Thread.Sleep(3000);
            SetStatusTextMethod("3");
            Thread.Sleep(3000);
            SetStatusTextMethod("0");
        }
        public void SetStatusTextMethod(string statusText)
        {
            label1.Text = statusText;
            label1.Refresh();
        }
    }
    public class Worker
    {
        Form1 guiForm;    // holds form where "control-to-be-changes" is found.
        public Worker(Form1 _guiForm)
        {
            guiForm = _guiForm;
        }
        public void DoWork()   // while steps are being done - form can easily be moved around... is not locked!
        {
            // put "1/3" on form.
            guiForm.Invoke(guiForm.mySetStatusTextDelegate, "1");
            Thread.Sleep(3000);
            // put "2/3" on form.
            guiForm.Invoke(guiForm.mySetStatusTextDelegate, "2");
            Thread.Sleep(3000);
            // put "3/3" on form.
            guiForm.Invoke(guiForm.mySetStatusTextDelegate, "3");
            Thread.Sleep(3000);
            guiForm.Invoke(guiForm.mySetStatusTextDelegate, "0");
        }
    }
}