-2

我有一个 WPF 按钮和一个列表框。当我按下按钮时,它使用异步并等待运行数字生成器。数字生成器只是一个生成整数的 for 循环。循环中还有一个 Iprogress 报告整数。主线程中的一个函数,更新 UI 中的 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) 运行,它的数字被忠实地注册了

4

1 回答 1

2

基本上,问题在于 ReportProgress 方法在您的报告对象的 LastIntegerGenerated 属性得到更新后被调用。

解决此问题的最简单方法是每次调用progress.Report 时使用一个新的报表对象。移动线:

ProgressReportModel report = new ProgressReportModel();

在你的 for 循环中,你应该不再需要延迟。

于 2021-01-04T18:57:19.527 回答