【问题标题】:Add items to DataGrid in another thread在另一个线程中将项目添加到 DataGrid
【发布时间】:2020-09-29 21:35:27
【问题描述】:

我正在尝试使用 WPF 以一种 UI 不会冻结的方式将项目添加到 DataGrid。

背景: 我有一个 IP 地址列表。使用这些 IP 地址,应确定更多信息,例如平。这意味着,我会遍历 IP 列表的每一项,根据 IP 确定数据并将结果插入到新列表中。这个新列表的内容应该显示在 DataGrid 中。

现在是这样,大约有 4000 个 IP。估计每秒大约有 15 个条目将添加到 DataGrid 列表中。但是,只有在一个列表中的所有项目都已处理并添加到新列表中后,才会显示该列表。

我的目标是让它看起来像这样: https://www.youtube.com/watch?v=xWC1GvfCI0I

您是否知道如何最好地解决这个问题?这是我尝试的最后一种方式:

public void Get()
    {
        Task.Run(() =>
        {
            using (var client = new WebClient())
            {
                var ips = client.DownloadString("http://monitor.sacnr.com/list/masterlist.txt");

                using (var reader = new StringReader(ips))
                {
                    for (string ip = reader.ReadLine(); ip != null; ip = reader.ReadLine())
                    {
                        this.Servers.Add(this._sacnr.GetServerProperties(ip));
                    }
                }
            }
        });
    }

谢谢。

【问题讨论】:

  • 好的,我现在明白你的意思了,你希望 UI 与你的 get 函数同时更新,也就是说,datagrid 在检索值时应该自动更新,如附加的 YouTube 链接中所示。您需要使用 IProgress 接口。 @N.Dogac 已经在上面发布了一个链接。我现在会删除我的答案
  • 我现在尝试这样做:Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => this.Get())); 但它仍然冻结。我保留了 Get() 方法。我是不是理解错了?
  • 使您的方法异步并尝试在 DownloadStringAsync 或 ReadlineAsync 上等待,这应该可以解决问题。或者只是等待 Task.run()。我会尝试所有 3 个选项,看看哪个最适合。
  • 如果你想像在视频中一样更新列表,我会绑定到 ObservableCollection 而不是常规列表,然后将项目循环添加到它。这将导致 DataGrid 的平滑更新,ObservableCollection 默认实现 InotifyProperty。

标签: c# wpf datagrid


【解决方案1】:

我现在就是这样做的。

我这样称呼我的方法:Task.Factory.StartNew(() => this.Get());

然后我使用我的方法是这样的:

public void Get()
{
    var sacnr = new SacnrConnector();

    using (var client = new WebClient())
    {
        var ips = client.DownloadString("http://monitor.sacnr.com/list/masterlist.txt");

        using (var reader = new StringReader(ips))
        {
            for (string ip = reader.ReadLine(); ip != null; ip = reader.ReadLine())
            {
                var server = sacnr.GetServerProperties(ip);

                // Here I use BeginInvoke to add elements to my ObservableCollection
                Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new ParameterizedThreadStart(AddItem), server);
            }
        }
    }
}

private void AddItem(object server)
{
    this.Servers.Add((Server)server);
}

而且它有效!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多