Incrementally loading items in a listview

0

I have adopted the following example from MSDN for incrementally loading thumbnails in a list view in an WinRT App:

https://code.msdn.microsoft.com/windowsapps/Data-Binding-7b1d67b5

I would like to remove the "await Task.Delay(10)" line below. When I do, I get a warning that the method lacks an await operator.

protected async override Task<IList<object>> LoadMoreItemsOverrideAsync(System.Threading.CancellationToken c, uint count)
        {
            uint toGenerate = System.Math.Min(count, _maxCount - _count);

            // Wait for work 
            await Task.Delay(10);

            // This code simply generates
            var values = from j in Enumerable.Range((int)_count, (int)toGenerate)
                         select (object)_generator(j);
            _count += toGenerate;

            return values.ToArray();
        }

I tried rewrite the method and wrap the entire method in a task asfollows:

protected async override Task<IList<object>> LoadMoreItemsOverrideAsync(System.Threading.CancellationToken c, uint count)
            {
     return await  Task.Run(() => {
                uint toGenerate = System.Math.Min(count, _maxCount - _count);

                // This code simply generates
                var values = from j in Enumerable.Range((int)_count, (int)toGenerate)
                             select (object)_generator(j);
                _count += toGenerate;

                return values.ToList<object>();
            });
}

However, I am getting threading exceptions:

Exception: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

It seems like I need to run this on the UI Thread? But I don't have access to the Dispatcher.

Looking for some recommendations

c#
winrt-xaml
winrt-async
asked on Stack Overflow May 29, 2015 by user82383

1 Answer

0

I think you're looking in the wrong place. Granted, I'm taking a bit of a stab in the dark, but since the rest looks innocuous something in your _generator(int) method most likely needs to run on the UI thread. (Perhaps it is not the UI thread per se, but something needs to be run on the same thread as something else. Since you mention thumbnails, the most likely reason is you have a GDI+ Graphics object created in one thread and are trying to manipulate it in another.)

My suggestion would be to closely examine your _generator(int) method and make an async version of it which takes care of making sure code is run on the correct thread. This way encapsulation is maintained and your LoadMoreItemsOverrideAsync callback does not need to understand anything about the inner workings of _generator.


As a side note, adding a 10ms delay is almost decidedly not the correct action, unless there is some race condition you are actively trying to avoid. (What does "wait for work" in the comment mean? If you are indeed waiting for work, shouldn't you be awaiting another task to finish, not an arbitrary 10ms?)

The warning you are most likely getting is trying to tell you, "You have marked this method with the async keyword, but nothing about it is asynchronous. Did you forget an await somewhere?"

If as a last resort you have no choice but to run the code synchronously, do just that. Put a comment in there, and acknowledge the situation by disabling that particular warning for the method.

answered on Stack Overflow May 29, 2015 by lc. • edited May 29, 2015 by lc.

User contributions licensed under CC BY-SA 3.0