I have a Login Form (which has a label that will show status of background process, username and password text boxes, Login and Cancel buttons) along with that I have a background worker to do some time taking task (in the meanwhile when Login Form loads and user provide details in text boxes).Background task keep running while the user will be providing username and password on Login Form. As soon as the user hits the Login button I want to check the status if the background process has completed successfully and then only it should proceed (launch the MainForm)Otherwise should pop-up error. Following is what I did to achieve but the 'while()' strategy doesn't look elegant. Is there any more appropriate way?  public partial class LoginForm : Form    {        private static BackgroundWorker bw = new BackgroundWorker();        private static ManualResetEvent mre = new ManualResetEvent(false);        enum status        {            Blank,            Success,            Error        };        public LoginForm()        {            InterimProceedings();            InitializeComponent();        }        private void InterimProceedings()        {            bw.DoWork += new DoWorkEventHandler(bw_DoWork);            bw.RunWorkerCompleted +=             new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);            if (!bw.IsBusy)            {                bw.RunWorkerAsync();            }            else            {                throw new InvalidOperationException(BackgroundWorker is busy);            }        }        private static void bw_DoWork(object sender, DoWorkEventArgs e)        {          //  Time taking task              mre.Set();        }        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)        {            if (!(e.Error == null))            {                this.lbl_status.Text = Cannot proceed, Error occured;                appStatus = status.Error;            }            else            {                this.lbl_status.Text = Good to go...;                appStatus = status.Success;            }        }        private void btn_login_Click(object sender, EventArgs e)        {            mre.WaitOne();            if(appStatus == status.Success)            {                // Proceed with intended work            }            else            {                // Pop-up error occurred            }        }}
Check before proceeding if the task in BackgroundWorker has completed
c#;multithreading;.net;winforms
The preferred solution for this kind of problem is to use async-await. It might seem like black magic at first, but once you get the hang of it, it can be extremely powerful, and elegant.public partial class LoginForm : Form{    private readonly Task _preLoginTask;    public LoginForm()    {        InitializeComponent();        _preLoginTask = PerformPreLoginWorkAsync();    }    private async Task PerformPreLoginWorkAsync()    {        lbl_status.Text = @Pre login work started;        await Task.Run(() =>        {            // Long running work runs on thread pool thread            Thread.Sleep(TimeSpan.FromSeconds(5));        });        lbl_status.Text = @Pre login work completed;    }    private async void btn_login_ClickAsync(object sender, EventArgs e)    {        btn_login.Enabled = false;        try        {            lbl_status.Text = @Waiting for pre login work to complete;            await _preLoginTask;            // Continue with the rest of the login here            lbl_status.Text = @Logged in;        }        catch (MyKnownException recoverableException)        {            lbl_status.Text = recoverableException.Message;        }        btn_login.Enabled = true;    }}This MSDN article is quite good if you want to pick up the basics quickly. 