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
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.
User contributions licensed under CC BY-SA 3.0