C# background worker to update status label

不问归期 提交于 2020-01-03 08:47:08

问题


This should be a fairly simple thing; however, I've been unable to figure this out.

/// This section is located in the InitializeComponent() method
/// form's class, i.e. partial class frmMain { .... }
this.bgw = new System.ComponentModel.BackgroundWorker();
this.bgw.WorkerReportsProgress = true;
this.bgw.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bgw_DoWork);
this.bgw.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bgw_ProgressChanged);

/// This code is located in public partial class frmMain : Form { .... }
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
        Thread.Sleep(100); // Wait 100 milliseconds
        //Console.WriteLine(i);
        bgw.ReportProgress(i);
    }
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Update status label
    lblStatus.Text = e.ProgressPercentage.ToString();
}
// New code added to question after edit
public frmMain()
{
    InitializeComponent();
    bgw.RunWorkerAsync();
    // some more stuff...
}

The background worker is running correctly; however, it is not correctly updating its progress. If I uncomment the commented line in the DoWork event, I able able to see the status updated correctly; however, the ProgressChanged event does not get triggered until after the task (heavy database computational stuff) in the main thread is finished.

This is using .NET Framework 4 and is a Windows Forms Application.

Edit

See the comments in the above code for where the code is located.

Some more details

The code that is being executed involves executing multiple queries on a database. I am not at liberty to disclose that code. As far as how that code is being executed, I actually do not know, as I was handed a .dll by another developer and was told to only use that when accessing the database....

Edit

The code in the "some more stuff" section was moved to be as follows

private void frmMain_Load(object sender, EventArgs e)
{
   // some more stuff... aka run queries!
}

回答1:


Your BackgroundWorker code is just fine. The problem is that you have code elsewhere (in this case, in your constructor or FormLoad) that is blocking the UI thread (by performing a synchronous database request). You need to do something to ensure that this code is run in a non-UI thread. This could mean using this existing BackgroundWorker to perform those other long running tasks; it could also be done by using Task.Factory.StartNew or some other threading mechanism to have it run in a non-UI thread.

Once the UI thread is not being blocked you will see the updates made in your `ProgressChanged event handler reflected in the UI.




回答2:


@Servy is of course correct.

I just wanted to chime in with this code that reproduces the problem:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        bgw.RunWorkerAsync();

        Task.Factory.StartNew(SomeMoreStuff);
    }

    private void SomeMoreStuff()
    {
        for (int i = 0; i < 5; i++)
        {
            Thread.Sleep(50);
            this.Invoke((Action)HogTheUIThread);
        }
    }

    private void HogTheUIThread()
    {
        Thread.Sleep(1000);
    }

    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 1; i <= 100; i++)
        {
            Thread.Sleep(100); // Wait 100 milliseconds
            //Console.WriteLine(i);
            bgw.ReportProgress(i);
        }
    }

    private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update status label
        lblStatus.Text = e.ProgressPercentage.ToString();
    }
}


来源:https://stackoverflow.com/questions/12044421/c-sharp-background-worker-to-update-status-label

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!