简体   繁体   中英

C# background worker frozen the GUI

I'm trying to use background worker to update a text label continuously, but for DoWork, if no loop used, it will only execute once, but if infinite loop is used, it freezes the GUI, any idea to solve this? Really appreciate!!! I'm pretty new to C# and still trying to learn.

Here's my code:

This in the main form:

backgroundWorkerX.DoWork += backgroundWorkerX_DoWork;
backgroundWorkerX.ProgressChanged += backgroundWorkerX_ProgressChanged;
backgroundWorkerX.WorkerReportsProgress = true;
backgroundWorkerX.RunWorkerAsync();

Then:

public void backgroundWorkerX_DoWork(object sender, DoWorkEventArgs e)
{
    X = -(RSSI_PI1_ST1);
    backgroundWorkerX.ReportProgress(X);
}


public void backgroundWorkerX_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label9.Text = e.ProgressPercentage.ToString();
}

public void backgroundWorkerX_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{

}

[...] if no loop used, it will only execute once

This is the expected behavior. It will do the thing it's expected and then call RunWorkerCompleted .

[...] but if infinite loop is used, it freezes the GUI.

You don't present a loop in your question. So I'll make an assumption and will give you an educated guess that it actually consumes all the CPU, and therefore crashes the GUI.

// I assume that you loop like this somehow.
do 
{
    X = -(RSSI_PI1_ST1);
    backgroundWorkerX.ReportProgress(X);
} while (true);

Try to add something to "slow it down" once in a while. Otherwise it will just run and run as fast as possible, and therefore consume all the CPU available. Remember that everytime you use ReportProgress it will be rendered by the GUI-thread. And this will execute very often and not leave a lot of resources for the GUI thread to respond to other things. Below I use Thread.Sleep , which will pause the thread for half a second. But remember that you will only want to do this in a background thread.

do 
{
    X = -(RSSI_PI1_ST1);
    backgroundWorkerX.ReportProgress(X);
    Thread.Sleep(500);
} while (true);

I would also consider doing this another way. If you actually have the need of pausing the thread, you might as well do it with a Timer . Thread.Sleep will lock the thread, and may therefore not be what you really want. From this answer :

Process() // method to be called after regular interval in Timer
{
    // lengthy process, i.e. data fetching and processing etc.

    // here comes the UI update part
    Dispatcher.Invoke((Action)delegate() { /* update UI */ });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM