Virtual grid and the (slow) remote cache

4 posts, 0 answers
  1. Andrea
    Andrea avatar
    52 posts
    Member since:
    Oct 2012

    Posted 15 Dec 2015 Link to this post

    Hello, first of all I want to clarify i have not an issue with the product, what I'm trying to do is to support a very specific scenario.

    The scenario is the following: a read-only grid, showing data from a query to a large remote database table, on a client with good networking speed and high latency.

    The requirement is that the user will have to work on a responsive local ui despite the high latency, so virtualization and data paging is used.

    The current implementation uses a virtual grid associated to a local cache that keeps in memory a small page of record, for example 500.

    At the very beginning the cache gets the record count to the server and pass this number as the RowCount to the grid.

    As the grid raise the event OnCellValueNeeded to get the row number 100,772 , the cache know that record 100,772 is out of its local bounds and will require to the server the records between (for example) 100,722 to 101,221. That's given the high latency requires little less a second, it is not a terrible issue, but... it is noticeable and somebody have the feeling of a not responsive UI, cause the server request is synchronous thus freezing the UI.

    I'm not a psychologist but i guess the bad feeling is caused by the fact the user did not requested the "get a new page operation", if i gave the user the "paging" control the user would have a good feeling, but I can't.

    I would like to exploit the human sensation about a smoot and responsive UI by running the query async, having the grid showing the value "#loading" on cells and then once the background worker finished loading the cache ask the grid, if the requested cell still is visible, to refresh the cell.

    So now i described the scenario, what i would like to ask community is if it is possible and how to :

    * have the oncellvalueneeded immediately return a dummy value for any datatype (including datetime cells) and launch the background worker to retrieve the data.

    * once the data is ready, ask the grid to refresh the {visible cells} intersecated with the {retrieved from the database data}

    Best regards

    Andrea

     

     

  2. Hristo Merdjanov
    Admin
    Hristo Merdjanov avatar
    710 posts

    Posted 17 Dec 2015 Link to this post

    Hi Andrea,

    Thank you for writing.

    First I would like to start with some good news that we are currently in the process of implementation of a virtual grid. The new control should be able to handle your type of scenario out of the box.

    For the time being my suggestion is that you perform this query one step ahead before you actually need the data. For example, you can always have a cached data for let`s say 1000 rows, and when you handle the CellValueNeeded event you can populate the grid cells with items from the cache. Knowing the index of the currently needed row source you can perform the query and load the data for the next 1000 rows in a separate cache before you actually need it. This operation can be async and run on a separate thread not freezing the UI. 

    In Windows Forms, you should always pay attention and update the controls only from the thread on which they were created. If you follow the suggested approach this should not be a problem because by the time you need the data it would have been loaded in the cache. Now I am sending you an example how RadGridView when data bound can be updated from another thread:
    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        private BindingList<Model> data = new BindingList<Model>();
     
        public RadForm1()
        {
            InitializeComponent();
     
            for (int i = 0; i < 2000; i++)
            {
                this.data.Add(new Model()
                {
                    FirstName = "James " + i,
                    LastName = "Wright " + i,
                    Gender = "male"
                });
            }
     
            this.radProgressBar1.ShowProgressIndicators = true;
            this.radGridView1.DataSource = this.data;
            this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
            this.radButton1.Click += radButton1_Click;
        }
     
        private void radButton1_Click(object sender, EventArgs e)
        {
            Thread backgroundThread = new Thread(
            new ThreadStart(() =>
            {
                for (int n = 0; n < 100; n++)
                {
                    Thread.Sleep(25);
                    this.radProgressBar1.BeginInvoke(
                        new Action(() =>
                        {
                            this.radProgressBar1.Value1 = n;
                        }));
     
                    this.radGridView1.BeginInvoke(
                        new Action(() =>
                        {
                            this.data.Add(new Model()
                            {
                                FirstName = "Maria " + n,
                                LastName = "Gomez " + n,
                                Gender = "female " + n
                            });
                        }));
                }
     
                MessageBox.Show("Thread completed!");
                this.radProgressBar1.BeginInvoke(
                    new Action(() =>
                    {
                        this.radProgressBar1.Value1 = 0;
                    }));
            }));
     
            backgroundThread.Start();
        }
    }
     
    public class Model
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Gender { get; set; }
    }

    I hope this helps. Should you have further questions please do not hesitate to write back.

    Regards,
    Hristo Merdjanov
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Andrea
    Andrea avatar
    52 posts
    Member since:
    Oct 2012

    Posted 17 Dec 2015 in reply to Hristo Merdjanov Link to this post

    Thank you for your reply, yes an option is to anticipate the user , maybe keep 3 pages, current, next and previous  and try to load data ahead on forward and back scrolling should be enough for me, that's a good idea.

     

    I'm just curious about what you are implementing on the grid virtual mode on the future, will that be based on Linq queries?

     

    Best Regards

    Andrea

  5. Hristo Merdjanov
    Admin
    Hristo Merdjanov avatar
    710 posts

    Posted 18 Dec 2015 Link to this post

    Hi Andrea,

    Thank you for writing back.

    I am glad that you have considered my suggestion helpful.

    Considering your question about the virtual grid, it is going to be a brand new control and not related to RadGridView. The present grid control is by design working with the prerequisite that all of the data will be available at all time. That is why the virtual mode providing options for querying data and loading it on demand is limited when it comes to filtering, sorting and grouping.

    The new control, on the other hand, will handle scenarios in which the data is queried. Internally, the virtual grid will not be built with LINQ, however, it will expose API through which you would be able to build LINQ queries. Filtering, sorting and paging support will be provided out of the box.

    I hope this information was helpful. Should you have further questions please do not hesitate to write back.

    Regards,
    Hristo Merdjanov
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top