在列表视图中逐步加载项目

时间:2015-05-29 04:26:49

标签: c# winrt-xaml winrt-async

我在MSDN中采用了以下示例,用于在WinRT应用程序的列表视图中逐步加载缩略图:

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

我想删除下面的“await Task.Delay(10)”行。 当我这样做时,我得到一个警告,该方法缺少await运算符。

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();
        }

我尝试重写该方法并将整个方法包装在一个任务中,如下所示:

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>();
            });
}

但是,我正在获得线程异常:

异常:应用程序调用了为不同线程编组的接口。 (来自HRESULT的异常:0x8001010E(RPC_E_WRONG_THREAD))

好像我需要在UI线程上运行它?但我无法访问Dispatcher。

寻找一些建议

1 个答案:

答案 0 :(得分:0)

我认为你在寻找错误的地方。当然,我在黑暗中采取了一些刺激,但由于其余部分在您的_generator(int)方法中看起来无害,因此很可能需要在UI线程上运行。 (也许它不是UI线程本身,但是某些东西需要在与其他东西相同的线程上运行。既然你提到缩略图,最可能的原因是你创建了一个GDI + Graphics对象一个线程,并试图在另一个线程中操纵它。)

我的建议是仔细检查你的_generator(int)方法并制作一个async版本,以确保代码在正确的线程上运行。这样就可以保持封装,并且LoadMoreItemsOverrideAsync回调不需要了解_generator的内部工作原理。

作为旁注,添加10毫秒的延迟几乎肯定正确的操作,除非您正在积极尝试避免某些竞争条件。 (评论中“等待工作”是什么意思?如果你确实在等待工作,你不应该等待另一项任务完成,而不是任意10ms吗?)

您最有可能发出的警告是试图告诉您,“您已使用async关键字标记此方法,但没有任何关于它的信息是异步的。您是否在某个地方忘记了await?”

如果作为最后的手段,你别无选择,只能同步运行代码,就这样做。在那里发表评论,并通过禁用该方法的特定警告来确认情况。