VirtualDataCollectionOnItemsLoading is called several times?

11 posts, 0 answers
  1. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 19 Aug 2013 Link to this post

    I have a bit specific scenario: i don't know size of the page before parsing server's answer. Also, i want to keep everything flexible enough (no special code for first call).
     So, my function is looking like this (viewmodel): 
    public MyViewModel(IProductSubSubCategoriesDataService dataService)
            {
                _dataService = dataService;
     
                SelectedIndex = String.Empty;
                VirtualDataCollection = new VirtualizingDataCollection(1, Constants.PAGE_SIZE_PRODUCT_SUB_SUB_CATEGORY); // 30 for now
            }
    }
     
    private void VirtualDataCollectionOnItemsLoading(object sender, VirtualizingDataCollectionItemsLoadingEventArgs e)
            {
                if (String.IsNullOrEmpty(SelectedIndex)) return;
     
                ThreadPool.QueueUserWorkItem(async o =>
                    {
                        var answerCached = await _dataService.ReadFromCacheAsync(SelectedIndex, e.StartIndex, e.Count);
                        if (answerCached.Status == AnswerDataServiceStatus.Ok)
                        {
                            DispatcherHelper.CheckBeginInvokeOnUI(() =>
                                {
                                    lock (locker)
                                    {
                                        VirtualDataCollection.ItemsLoading -= VirtualDataCollectionOnItemsLoading;
                                        VirtualDataCollection.Count = answerCached.TotalItems;
                                        VirtualDataCollection.LoadItems(e.StartIndex, answerCached.Collection);
                                        VirtualDataCollection.ItemsLoading += VirtualDataCollectionOnItemsLoading;
     
                                        IsBusy = false;
                                        Status = String.Empty;
                                    }
                                });
     
                        }
                        else
                        {
                            var answer = await _dataService.RequestServerAsync(SelectedIndex, e.StartIndex, e.Count);
                            if (answer.Status == AnswerDataServiceStatus.Ok) // && answer.Collection.SequenceEqual(VirtualDataCollection.))
                            {
                                DispatcherHelper.CheckBeginInvokeOnUI(() =>
                                    {
                                        lock (locker)
                                        {
                                            VirtualDataCollection.ItemsLoading -= VirtualDataCollectionOnItemsLoading;
                                            VirtualDataCollection.Count = answer.TotalItems;
                                            VirtualDataCollection.LoadItems(e.StartIndex, answer.Collection);
                                            VirtualDataCollection.ItemsLoading += VirtualDataCollectionOnItemsLoading;
     
                                            IsBusy = false;
                                            Status = String.Empty;
                                        }
                                    });
                            }
                            else
                            {
                                if (String.Equals(Status, MainResources.Loading_process))
                                    DispatcherHelper.CheckBeginInvokeOnUI(() => Status = MainResources.No_network_available);
                            }
                        }
                    });
            }
     
    public void OnNavigatedTo()
            {
                //ItemsList = null;
                Status = MainResources.Loading_process;
                VirtualDataCollection.ItemsLoading += VirtualDataCollectionOnItemsLoading;
     
                VirtualDataCollection.Count = 1;
    }
     
    public void OnNavigatedFrom()
            {
                SelectedIndex = String.Empty;
     
                VirtualDataCollection.ItemsLoading -= VirtualDataCollectionOnItemsLoading;
                VirtualDataCollection.Clear();
     
                Cleanup();
    }

    One of the problems that i faced was that first VirtualDataCollectionOnItemsLoading() is called at the page construction time. But i'm getting actual SelectedIndex (just product category index) only in the OnNavigatedTo().
    Solution is quite simple: no subscription by default, unsubscribe while navigatingFrom, subscribe while navigatingTo the page again.

    Now i'm getting another problem: _dataService.ReadFromCacheAsync() is called 2 times in a row, just one after another. And that produces quite notable delay, i see empty page for about 2 seconds.
    First callstack is quite okay: http://clip2net.com/s/5AYleg , but the second one is quite weird: http://clip2net.com/s/5AYjqc

    The most mysterious part for me - is that this appears only when i'm starting to read from cache. If i'm doing internet request, no second calls.


    Maybe i'm wrong at some point, so here is just raw information: when i'm loading page for the first time (no cache), everything is smooth and nice: i see animation while waiting for server answer, page is responsible, etc.But when i'm visiting the page second time, i expect to see cached results instantly. Instead, i see a non-responsible blank page for about 2 seconds (shit, its even longer than waiting for servers answer). 
    Any ideas?
  2. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 19 Aug 2013 Link to this post

    Okaay.. i just commented out caching, and still facing same problem: when i'm visiting page first time, everything is ok, but when i'm visiting the page for the second time, VirtualDataCollectionOnItemsLoading() calls 2 times, and 2 server requests are sent.

    EDIT: I assume, something is wrong with async call. I'm using just a common Bcl library.. hm, maybe i should check for updates.

    EDIT2: well, i used outdated Bcl indeed. However, problem is still there: updating didnt help.

    EDIT3: digging deeper shows, that something is wrong with threading here. Admin, can you, please call here a guy, who was working on this stuff? I guess, my approach is incompatible with DataBoundListBox design.

    I'm getting ReadFromCacheAsync() calls from different threads, but they are doing same stuff simultaneously.

    EDIT4: Okay, last observation for this evening for me. I removed QueueUserWorkItem() and asyncs - now VirtualDataCollectionOnItemsLoading() is calling only once. 
  3. DevCraft banner
  4. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 20 Aug 2013 Link to this post

    Well.. i have an idea to workaround this, to try to use BackgroundWorker. But afaik, async is more suitable for waiting tasks, and BackgroundWorker is more suitable for Cpu-intencive tasks. 

    EDIT: okay, i tried this one
    private Task<ProductSubSubCategoriesAnswer> Process(int a, int b)
            {
                return TaskEx.Run(() =>
                    {
                        var res = _dataService.RequestServerAsync(SelectedIndex, a, b);
                        return res;
                    });
            }
     
            private async void VirtualDataCollectionOnItemsLoading(object sender, VirtualizingDataCollectionItemsLoadingEventArgs e)
            {
                //BusyLevelInc();
                if (String.IsNullOrEmpty(SelectedIndex)) return;
     
                var an = await Process(e.StartIndex, e.Count);
     
                if (an.Status == AnswerDataServiceStatus.Ok) // && answer.Collection.SequenceEqual(VirtualDataCollection.))
                {
                        lock (locker)
                        {
                            VirtualDataCollection.ItemsLoading -= VirtualDataCollectionOnItemsLoading;
                            VirtualDataCollection.Count = an.TotalItems;
                            VirtualDataCollection.LoadItems(e.StartIndex, an.Collection);
                            VirtualDataCollection.ItemsLoading += VirtualDataCollectionOnItemsLoading;
     
                            IsBusy = false;
                            Status = String.Empty;
                        }
                     
                }
    }

    But still having same issue: when i'm visiting page for a second time, _dataService.RequestServerAsync(SelectedIndex, a, b); is calling twice. :(
  5. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 20 Aug 2013 Link to this post

    Tried BackgroundWorker - still same crap: while visiting page for a second time, it sends 2 server requests.

    var bw = new BackgroundWorker();
     
                bw.DoWork += async (o, args) =>
                    {
                        var res = await _dataService.RequestServerAsync(SelectedIndex, e.StartIndex, e.Count);
     
                        if (res.Status == AnswerDataServiceStatus.Ok) // && answer.Collection.SequenceEqual(VirtualDataCollection.))
                        {
                            DispatcherHelper.CheckBeginInvokeOnUI(() =>
                                {
                                    lock (locker)
                                    {
                                        VirtualDataCollection.ItemsLoading -= VirtualDataCollectionOnItemsLoading;
                                        VirtualDataCollection.Count = res.TotalItems;
                                        VirtualDataCollection.LoadItems(e.StartIndex, res.Collection);
                                        VirtualDataCollection.ItemsLoading += VirtualDataCollectionOnItemsLoading;
     
                                        IsBusy = false;
                                        Status = String.Empty;
                                    }
                                });
                        }
                    };
     
                bw.RunWorkerAsync();

    EDIT: made basic test again: if to comment away all async stuff in VirtualDataCollectionOnItemsLoading(). everything works fine: it is called only once.
    But i don't want to return to bloody callbacks because of this, there should be other workaround...

  6. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 20 Aug 2013 Link to this post

    Well... i ended up with moving cache reading to non-async.. page loads quite slow, about 0.5 sec, but that's much better than 2 seconds

    But now i got another problem: paging is failed to work. VirtualDataCollectionOnItemsLoading() is not calling. 
    Guys, can you, please, provide a sample of using DataBoundListBox with cache? I expected to spent at most an hour attaching cache, but now i had spent the whole day on it.

  7. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 21 Aug 2013 Link to this post

    Well.. now it works more or less, but caching (just reading file from isostorage and parsing it) freezes page for about 0.5-1 second. On the other pages, it work immediately.
    Taking into account, that server request takes 1-1.5 seconds, it is easier not to use cache at all.

    I hope, you're planning to do something with it in the nearest future :)
  8. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 21 Aug 2013 Link to this post

    Hi Vitalii,

    Thanks for writing.

    Since the thread has become a bit longer, we would like to kindly ask you to summarize the difficulties you are facing so that we can review them and be able to assist you quickly.

    Thanks for your understanding.

    Regards,
    Deyan
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINDOWS PHONE 7.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  9. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 21 Aug 2013 Link to this post

    Thanks for answer.
    Can you, please, provide a sample of VirtualDataCollection (using auto mode) with caching, additionaly to loading.
    Once page is loaded, results should be stored to file, and when user visit page for a second time,it should be recovered.

    The problem is that i have no idea, where to read data exactly, to avoid page freezes
  10. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 21 Aug 2013 Link to this post

    Hello Vitalii,

    Page freezes are caused by long-lasting operations performed on the UI thread. This is something you will face no matter whether you are using the VirtualizingDataCollection or not.

    When you fetch data either from the Internet or from the local storage, you should make sure it is fetched asynchronously and delivered to the UI thread via a Dispatcher as soon as it arrives. From that moment on you can load it into the VirtualizingDataCollection without experiencing any issues.

    Regards,
    Deyan
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINDOWS PHONE 7.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  11. Vitalii
    Vitalii avatar
    104 posts
    Member since:
    Jul 2013

    Posted 21 Aug 2013 Link to this post

    That's why im using threading.
    Anyway, I'll just send you sample project, so you would be able to take a glance :)
  12. Deyan
    Admin
    Deyan avatar
    2039 posts

    Posted 21 Aug 2013 Link to this post

    Hello Vitalii,

    Thanks for your understanding.

    To be able to attach a project you will have to open a new support thread. Since you've already done that, you can send us your project there and we will close all other threads.

    Thanks for your time.

    Regards,
    Deyan
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINDOWS PHONE 7.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
Back to Top
DevCraft banner