Асинхронный метод работает слишком быстро, чтобы обновить мой список в основном потоке

У меня есть кнопка WPF и список. когда я нажимаю кнопку, он использует асинхронность и ожидает запуска генератора чисел. Генератор чисел — это просто цикл for, производящий целые числа. Также в цикле находится Iprogress, сообщающий целое число. Функция в основном потоке обновляет listBox в пользовательском интерфейсе.

Проблема в том, что список не обновляется правильно, однако, если я помещаю Thread.sleep(10) в цикл for, он работает нормально. Похоже, что поток генерирует отчеты слишком быстро для обновления списка. Как я могу покончить с Thread.sleep(10) и точно обновить список? Правильно ли я подхожу к этому? Может кто-нибудь помочь? Спасибо.

          public partial class MainWindow : Window
{
    Progress<ProgressReportModel> progress = new Progress<ProgressReportModel>();
    public MainWindow()
    {
        InitializeComponent();
        progress.ProgressChanged += ReportProgress;
    }   
    private async void generateNumbersButton_Click(object sender, RoutedEventArgs e)
    {
        await Task.Run(()=>NumberGenerator.SimpleNumberGenerator(progress));
    }
    private void ReportProgress(object sender, ProgressReportModel e)
    {
        numbersListBox.Items.Add($"Integer generated {e.LastIntegerGenerated.ToString()}");
    }
}


static class NumberGenerator
{
    static public void SimpleNumberGenerator(IProgress<ProgressReportModel> progress)
    {
        ProgressReportModel report = new ProgressReportModel();
        int number = 10;
        for (int i = 0; i <= number ; i++)
        {
            report.LastIntegerGenerated = i;
            progress.Report(report);
            //Thread.Sleep(10);
        }
    }
}

public class ProgressReportModel
{
    public int LastIntegerGenerated { get; set; } = 0;
}

запустить без Thread.Sleep в цикле. Ожидание целых чисел от 0 до 10, но получение этого

запустить с Thread.Sleep(3)

запустите с Thread.Sleep(10), и числа будут зарегистрированы точно

1 ответ

По сути, проблема заключается в том, что метод ReportProgress вызывается после обновления свойства LastIntegerGenerated вашего объекта отчета.

Самый простой способ решить эту проблему — использовать новый объект отчета для каждого вызова progress.Report. Переместите строку:

      ProgressReportModel report = new ProgressReportModel();

быть в вашем цикле for, и вам больше не нужно вставлять эту задержку.

Другие вопросы по тегам