Anele Ngqandu Ответов: 3

Обновление метки данными из потока


Я пытаюсь обновить метку в windows forms. Действие происходит в отдельном классе, но пока действие происходит в отдельном классе. Этикетка должна быть обновлена, но, похоже, что-то не работает. Пожалуйста помогите

Ниже приведен обратный код формы ProcessingUI

Что я уже пробовал:

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;
    }
}


Тогда вот отдельный класс, который имеет действие, в основном его просто обновление. Теперь при обновлении я просто хочу передать запись, которая обновляется. Поэтому я вызываю метод из формы и использую его в этом классе.

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.
           }

       }
   }

3 Ответов

Рейтинг:
2

Gerry Schmitz

new ProcessingUI().UpdateStatus(record.RequestReference);//This is the method I am calling from the form.
Все, что вы делаете, это создаете несколько экземпляров "ProcessingUI form" ... и не "показывал" их.

Вам нужен "один экземпляр" вашей формы, который вы "показываете" и обновляете.


Anele Ngqandu

Привет, Джерри, если я создам 1 экземпляр вверху, я получу "исключение типа "системы.Исключения StackOverflowException' был брошен" ничего в стек трассировки и ничего в свойство innerexception

Рейтинг:
2

Anele Ngqandu

Привет Мацей, спасибо за ответ. Изначально я использовал back ground worker. у меня все еще была та же проблема, потому что значение, которое я ищу, находится внутри Processdata на этом foreach (запись var в dataCases), поэтому мне вроде как нужен способ получить это значение на стороне пользовательского интерфейса

Maciej Los

Итак, перейдите по ссылкам, которые я предоставил. Там вы найдете способ вызова элементов управления windows из потока за формой.

Anele Ngqandu

Кажется, я не могу попасть в backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) не уверен, что мне не хватает

Maciej Los

Лучший способ узнать это-отладить программу ;)

Рейтинг:
14

Richard Deeming

Одним из относительно простых решений было бы использование то Progress<T> класс[^], который заботится о кросс-потоковом доступе для вас.

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;    
    }
}


Anele Ngqandu

Большое спасибо Ричард