首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Windows运行时后台线程上运行代码

如何在Windows运行时后台线程上运行代码
EN

Stack Overflow用户
提问于 2014-12-01 12:36:23
回答 2查看 593关注 0票数 0

我使用增量加载来显示ListView项。我在后台线程中运行LoadDetails方法,使用Task.Run(...)不占用UI线程。

但是它仍然阻塞UI线程,并且它在完成任务之前不会呈现UI元素。

执行LoadDetails方法大约需要3秒才能完成。

代码语言:javascript
复制
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运行时应用程序)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-01 20:20:18

从你的问题中还不清楚你是如何测量3秒延迟的。对GetItemCounts()的调用本身需要3秒吗?如果是这样的话,这不是意料之中的事吗?延迟是您首先异步执行的原因,不是吗?

你发布的代码看起来不太正确。因为您的新TaskawaitLoadDetails()的调用,所以该任务将立即完成,而不会与实际工作同步。从不同的角度来看,您也可以避免直接通过Dispatcher调用。

我会写得更像这样的:

代码语言:javascript
复制
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()方法:

代码语言:javascript
复制
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();
}
票数 2
EN

Stack Overflow用户

发布于 2014-12-01 15:08:36

您的代码似乎正确地没有使用await阻止UI线程,但是由于LoadItemDetails()大概是在UI线程上被调用的,所以在方法完成其工作之前,它不会完成。

要解决这个问题,只需在调用await时忽略Task.Run(),所以类似于

代码语言:javascript
复制
Task.Run(() => LoadDetails(textBlock, item.Id));

应使LoadItemDetails()立即返回。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27228580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档