【问题标题】:C# async operation not waiting wp8.1C#异步操作不等待wp8.1
【发布时间】:2016-05-12 20:51:59
【问题描述】:

你好,我不知道为什么这个异步操作不等待

private async void scroller_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        if (isLoadingMore)
            return;
        if (scroller.VerticalOffset > scrollContent.ActualHeight - (Frame.ActualHeight + 300))
            await LoadMoreItems();
    }
    bool isLoadingMore = false;
    private async Task LoadMoreItems()
    {
        isLoadingMore = true;
        try
        {
            List<Items> itemsList = await App.ServiceClient.GetItems("bananas");//<-------Doesn't wait
            foreach (Items in itemsList)
                listView.Items.Add(c);
        }
        catch { }
        isLoadingMore = false;
    }

这是与另一个异步任务的后端调用

public async Task<List<Items>> GetItems(string selector)
    {
        HttpClient client = new HttpClient();
        var request = new HttpRequestMessage()
        {
            RequestUri = new Uri(myUrl),
            Method = HttpMethod.Get,
        };
        request.Headers.Add("Accept", "application/json");
        List<Items> items = null;
        var task = await client.SendAsync(request).ContinueWith(
            async (s) =>
            {
                try
                {
                    string Result = await s.Result.Content.ReadAsStringAsync();
                    if (s.Result.IsSuccessStatusCode)
                        items= JsonConvert.DeserializeObject<List<Items>>(Result);
                }
                catch
                { }
            });
        return items;
    }

问题在于嵌套等待或在 scoll 视图中。 我找到了this,但我认为情况并非如此。

【问题讨论】:

  • 请提供minimal reproducible example(特别是“最小”部分)。到目前为止,async void 看起来很可疑 - 很可能您对预期行为的期望与一劳永逸不同。

标签: c# asynchronous windows-phone-8 nested frontend


【解决方案1】:

事件处理程序是 async void,因此 UI 永远不会等待,如果您无法处理多个 ViewChanged事件,您有两种选择:

1-在执行异步调用时禁用滚动条:

private async void scroller_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
    scroller.Enabled = false;
    try
    {
        if (isLoadingMore)
            return;
        if (scroller.VerticalOffset > scrollContent.ActualHeight - (Frame.ActualHeight + 300))
            await LoadMoreItems();
    }
    finally{ scroller.Enabled = true; }
}

2-如果有另一个事件处理程序正在运行,则不要执行代码:

bool runnning = false

private async void scroller_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
    if(running)
        return;

    runnning = true;
    try
    {
        if (isLoadingMore)
            return;
        if (scroller.VerticalOffset > scrollContent.ActualHeight - (Frame.ActualHeight + 300))
            await LoadMoreItems();
    }
    finally{ running = false; }
}

【讨论】:

  • 问题出在 List itemsList 中,它不会等待完成后端调用并继续到 foreach 获得空引用异常
  • 嗯,几乎 100% 肯定,如果这是因为异步 lambda 的问题,它与使用 TaskFactory.StartNew 和 Task.Run 相同,如果 lambda 是异步的,则 StartNew 不会等待运行会,不同之处在于运行会为您解包任务,所以如果您这样做,它可能会等待:var task = await client.SendAsync(request).ContinueWith(theLambda).Unwrap()。这里有更多信息:msdn.microsoft.com/en-us/library/dd780917%28v=vs.110%29.aspx
猜你喜欢
  • 2017-02-15
  • 2019-09-24
  • 1970-01-01
  • 2016-12-26
  • 1970-01-01
  • 2022-01-05
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多