Click here to Skip to main content
15,887,596 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to update a label in windows forms. The action is happening in a separate class but while the action is happening on a separate class. The label should be updated, but things seem to be not working. Kindly assist

Below is the Back code of the form ProcessingUI

What I have tried:

C#
public partial class ProcessingUI : Form
{
    private void start_Click(object sender, EventArgs e)
    {
        StartProcessingTask();
    }

     private void StartProcessingTask()
    {
        if (_isRunning)
            return;

        _isRunning = true;

        _taskToken = new CancellationTokenSource();

            Task.Factory.StartNew(() =>
            {
                while (_isRunning)
                {

                    var data = _processing.Processdata(lblCounter, _taskToken);
                    if (data.Success)
                        _isRunning = false;
                    if (_taskToken.IsCancellationRequested)
                        return;
                }

            });

    }

    public delegate void SetStatusCallback(string message);
    public void UpdateStatus(string message)
    {
        if (this.lblCounter.InvokeRequired)
        {

            this.Invoke(new SetStatusCallback(UpdateStatus), 
                 message);                                   
        }
        else
            this.lblCounter.Text = message;
    }
}


Then here is a separate class that has the action, basically its just updating. Now on update I just want to pass the record that is being updated. So i call the Method from the form and use it in this class.

C#
public class Processing
   {
        public Results Processdata(CancellationTokenSource taskToken)
       {
       foreach (var record in dataCases)
               {
          //Doing other things here like updating
            new ProcessingUI().UpdateStatus(record.RequestReference);//This is the method I am calling from the form.
           }

       }
   }
Posted
Updated 12-Jun-18 5:01am

new ProcessingUI().UpdateStatus(record.RequestReference);//This is the method I am calling from the form.
All you are doing is creating multiple instances of the "ProcessingUI form" ... and not "showing" them.

You need "one instance" of your form, that you "show" and update.
 
Share this answer
 
Comments
Anele Ngqandu 12-Jun-18 1:03am    
Hi Gerry, if I create 1 instance at the top, I get "Exception of type 'System.StackOverflowException' was thrown" Nothing in stack trace and nothing in Innerexception
One relatively simple solution would be to use the Progress<T> class[^], which takes care of the cross-thread access for you.
C#
public class Processing
{
    public Results ProcessData(IProgress<string> statusReporter, CancellationToken cancellationToken)
    {
        foreach (var record in dataCases)
        {
            // Doing other things here like updating
            
            // Update the status:
            statusReporter.OnReport(record.RequestReference);
            
            // Stop if the task has been cancelled:
            cancellationToken.ThrowIfCancellationRequested();
        }
    }
}

public partial class ProcessingUI : Form
{
    private void start_Click(object sender, EventArgs e)
    {
        StartProcessingTask();
    }

    private void StartProcessingTask()
    {
        if (_isRunning)
            return;
        
        _isRunning = true;
        _taskToken = new CancellationTokenSource();
        
        CancellationToken cancellationToken = _taskToken.Token;
        IProgress<string> statusReporter = new Progress<string>(UpdateStatus);

        Task.Run(() =>
        {
            while (_isRunning)
            {
                var data = _processing.ProcessData(lblCounter, cancellationToken);
                if (data.Success)
                {
                    _isRunning = false;
                }
                else
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }
            }
        });
    }

    private void UpdateStatus(string message)
    {
        lblCounter.Text = message;    
    }
}
 
Share this answer
 
Comments
Anele Ngqandu 12-Jun-18 13:52pm    
Thanks a lot Richard
 
Share this answer
 
Comments
Anele Ngqandu 12-Jun-18 3:39am    
HiMaciej, thanks for the reply. Initially i was using back ground worker. still had the same issue because the value that am looking for is inside Processdata on that foreach (var record in dataCases) so I kinda need a way to get that value to the UI side
Maciej Los 12-Jun-18 3:52am    
So, follow the links i'd provided. There you'll find a way how to invoke windows controls from thread behind the form.
Anele Ngqandu 12-Jun-18 4:42am    
Cant seem to be hitting the backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) not sure what am I missing
Maciej Los 12-Jun-18 6:35am    
The best way to find out is to debug the programme ;)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900