我使用增量加载来显示ListView
个项目。我使用LoadDetails
在后台线程中运行Task.Run(...)
方法,以便不忙于UI线程。
但它仍会阻止UI线程,并且在完成任务之前它不会呈现UI元素。
执行LoadDetails方法大约需要3秒钟才能完成。
private async void LoadItemCounts(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (args.Phase != 6)
{
throw new Exception("Not in phase 6");
}
var item = args.Item as ItemModel;
var templateRoot = (Grid)args.ItemContainer.ContentTemplateRoot;
var textBlock = (TextBlock)templateRoot.FindName("textBlock");
await Task.Run(() => LoadDetails(textBlock, item.Id));
}
private async Task LoadDetails(TextBlock textBlock, string id)
{
int count = await DataSource.GetItemCounts(id);
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
textBlock.Text = count.ToString();
});
}
如何解决这个问题,以免它阻止UI线程?感谢。
(它是Windows Phone运行时应用)
答案 0 :(得分:2)
从您的问题中不清楚您是如何测量3秒延迟的。调用GetItemCounts()
本身需要3秒钟吗?如果是这样,那不是预期的吗?延迟是你首先异步执行的原因,不是吗?
您发布的代码看起来并不十分正确。由于您的新Task
没有await
对LoadDetails()
的调用,该任务将立即完成,而不会与正在进行的实际工作同步。换句话说,您也可以避免直接通过Dispatcher
拨打电话。
我会写更像这样的东西:
private async void LoadItemCounts(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (args.Phase != 6)
{
throw new Exception("Not in phase 6");
}
var item = args.Item as ItemModel;
var templateRoot = (Grid)args.ItemContainer.ContentTemplateRoot;
var textBlock = (TextBlock)templateRoot.FindName("textBlock");
await LoadDetails(textBlock, item.Id);
}
private async Task LoadDetails(TextBlock textBlock, string id)
{
int count = await DataSource.GetItemCounts(id);
textBlock.Text = count.ToString();
}
即。只要您继续等待UI线程,就不需要通过Dispatcher
进行调用。请注意,上面假设您需要LoadDetails()
方法,大概是因为您从多个地方调用它,有些因某些原因需要此特定实现。但请注意,您可以像这样编写LoadItemCounts()
方法,并完全省略LoadDetails()
方法:
private async void LoadItemCounts(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (args.Phase != 6)
{
throw new Exception("Not in phase 6");
}
var item = args.Item as ItemModel;
var templateRoot = (Grid)args.ItemContainer.ContentTemplateRoot;
var textBlock = (TextBlock)templateRoot.FindName("textBlock");
textBlock.Text = (await DataSource.GetItemCounts(id)).ToString();
}
答案 1 :(得分:1)
看起来您的代码使用await正确地阻止了UI线程,但由于可能在UI线程上调用LoadItemDetails()
,因此在方法完成其工作之前它不会完成。 / p>
要解决此问题,请在调用await
时忽略Task.Run()
,这样就像
Task.Run(() => LoadDetails(textBlock, item.Id));
应立即让LoadItemDetails()
返回。