将大量项目添加到DataGrid时,UI冻结 [英] UI freezes when adding great amount of items to a DataGrid

查看:68
本文介绍了将大量项目添加到DataGrid时,UI冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到了一个DataGrid,在处理了在BackgroundWorker内执行的更新功能之后,该数据网格已填充了多个项目.

I got a DataGrid which is getting filled with several items after an update function has been processed which is executed within a BackgroundWorker.

BackgroundWorker实际上请求一个JSON API并解析传入的响应.在此过程中,UI根本没有被锁定,所有内容仍处于响应状态.现在,当使用先前获取的响应填充DataGrid时,UI会锁定并冻结,直到添加了所有项目.

The BackgroundWorker actually requests a JSON API and parses the incoming response. In that process, the UI is not locked at all, everything is still responsive. Now, when filling the DataGrid with the previously fetched response, the UI locks and freezes until all items have been added.

代码:

更新方法:

public override void Update()
{
    CanUpdate = false;
    AddEverythingButtonVisible = false;

    var worker = new BackgroundWorker();
    worker.DoWork += (s, e) =>
    {
        // Item.Search is sending a HTTP request, everything is responding
        foreach (Item item in Item.Search(_SearchText, _SearchLevelMin, _SearchLevelMax, _SearchRarity, _SearchType,_SearchRemoveUnavailable))
        {
            // after the response was parsed, the lock begins at this point when adding items by using the UI thread
            Execute(() => ItemCollection.Add(new ProfitItemViewModel(new ProfitItem(item))));
        }
     }
 }

Execute是一个小助手功能,用于在单独的线程(BackgroundWorker)中访问UI线程,其外观如下:

Execute is a little helper function in order to access the UI thread while being in an seperate thread (BackgroundWorker) and looks as follows:

protected void Execute(System.Action action)
{
    if (Dispatcher.CheckAccess())
    {
        action.Invoke();
    }
    else
    {
        Dispatcher.BeginInvoke(DispatcherPriority.DataBind, action);
    }
}

我阅读了有关BeginInvokeInvoke的信息,并做出了以下决定:执行操作时,UI线程一定不要停止响应.因此,我最终实现了BeginInvoke,但是UI在更新时仍然冻结并锁定.

I had a read about BeginInvoke and Invoke and came to the decision, that the UI thread must not stop responding when the actions are performed. So I ended up implementing BeginInvoke but the UI still freezes and locks when updating.

那么,有什么解决方案可以在DataGrid装满后不锁定整个应用程序吗?

Well, is there any solution for not locking my entire application while my DataGrid is getting filled?

已更新有效代码:

var searchResults = Item.Search(_SearchText, _SearchLevelMin, _SearchLevelMax, _SearchRarity, _SearchType, _SearchRemoveUnavailable);
var compiledSearchResults = searchResults.Select(item => new ProfitItemViewModel(new ProfitItem(item)));
foreach (ProfitItemViewModel item in compiledSearchResults)
    Execute(() => ItemCollection.Add(item));

推荐答案

您要分别添加项目,每个项目作为单独的调用调用,这会大大降低UI的速度.而是在一个UI调用中添加尽可能多的项目.它可能会导致暂时的故障,但会比一连串的单次呼叫快得多.

You are adding items individually, each as a separate invoke call, which would very much slow down the UI. Rather, add as many items as you can in a single UI call. It may cause a temporary glitch, but will be much faster than a bunch of single calls.

此外,您还在UI调用中创建对象.如果它们不是依赖对象,请在进行UI调用之前创建它们,以节省一些UI功能.

Also, you are creating objects inside the UI call. If they aren't dependency objects, create them before you make the UI call to save some UI power as well.

经验法则:在UI线程之外尽您所能,并且只在必须在UI线程上完成的UI线程上工作(在您的情况下,更新ItemCollection).

Rule of thumb: do was much as you can outside the UI thread as you can, and only do work on the UI thread that has to be done on the UI thread (in your case, updating the ItemCollection).

示例:

var searchResult = Item.Search(_SearchText, _SearchLevelMin, _SearchLevelMax, _SearchRarity, _SearchType,_SearchRemoveUnavailable));

var compiledList = searchResult.Select(item => new ProfitItemViewModel(new ProfitItem(item))).ToArray();

Execute(() => {
    foreach (Item item in compiledList)
    {
        ItemCollection.Add(item);
    }
});

还可以考虑使用DeferRefresh来加快添加速度,例如:

Also consider using DeferRefresh to speed up the adds like so:

Execute(() => {
    using(ItemCollection.DeferRefresh()) {
        foreach (Item item in compiledList)
        {
            ItemCollection.Add(item);
        }
    }
});

这篇关于将大量项目添加到DataGrid时,UI冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆