Updating UI from a background thread which is called in a loop in main UI when the thread finishes

前端 未结 1 497
傲寒
傲寒 2020-12-04 00:08

I have a WinForms application that is calling a business class method that performs some heavy duty action taking about 5 seconds for each call. The main form calls this met

相关标签:
1条回答
  • 2020-12-04 00:37

    Add a Winforms Project, Drop a Label Control on the Form , Copy-Paste this code and Hit F5

    [EDIT]: Updated with the business class comment from the user

    NB: My form class is named Form3. You may have to change your Program.cs or vice-versa.

    using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public class BusinessClass
        {
            public int MyFunction(int input)
            {
                return input+10;
            }
        }
    
        public partial class Form3 : Form
        {
            private BackgroundWorker _worker;
            BusinessClass _biz = new BusinessClass();
            public Form3()
            {
                InitializeComponent();
                InitWorker();
            }
    
            private void InitWorker()
            {
                if (_worker != null)
                {
                    _worker.Dispose();
                }
    
                _worker = new BackgroundWorker
                {
                    WorkerReportsProgress = true,
                    WorkerSupportsCancellation = true
                };
                _worker.DoWork += DoWork;
                _worker.RunWorkerCompleted += RunWorkerCompleted;
                _worker.ProgressChanged += ProgressChanged;
                _worker.RunWorkerAsync();
            }
    
    
            void DoWork(object sender, DoWorkEventArgs e)
            {
                int highestPercentageReached = 0;
                if (_worker.CancellationPending)
                {
                    e.Cancel = true;
                }
                else
                {
                    double i = 0.0d;
                    int junk = 0;
                    for (i = 0; i <= 199990000; i++)
                    {
                        int result = _biz.MyFunction(junk);
                        junk++;
    
                        // Report progress as a percentage of the total task.
                        var percentComplete = (int)(i / 199990000 * 100);
                        if (percentComplete > highestPercentageReached)
                        {
                            highestPercentageReached = percentComplete;
                            // note I can pass the business class result also and display the same in the LABEL  
                            _worker.ReportProgress(percentComplete, result);
                            _worker.CancelAsync();
                        }
                    }
    
                }
            }
    
            void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Cancelled)
                {
                    // Display some message to the user that task has been
                    // cancelled
                }
                else if (e.Error != null)
                {
                    // Do something with the error
                }
            }
    
            void ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                label1.Text =  string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
            }
        }
    }
    

    With this you can achieve Cancel functionality also very easily. Observe that during initialisation, I set the WorkerSupportsCancellation = true & then I check for _worker.CancellationPending in the DoWork. So, if you want to cancel the process by a Cancel Button click, then you will write this code in the button handler- _worker.CancelAsync();

    0 讨论(0)
提交回复
热议问题