0

很简单,这是我的代码:

/// <summary>
/// Fetches the JSON string from the URL.
/// </summary>
/// <param name="url">URL to download the JSON from.</param>
/// <returns>JSON formatted string</returns>
private static string GetJsonResponse(string url)
{
    var result = DownloadString(url).Result;
    System.Diagnostics.Debug.WriteLine("Downloaded from {0} with result = {1}", url, result);
    return result;
}

private static async Task<string> DownloadString(string feedUrl)
{
    var result = "";
    System.Diagnostics.Debug.WriteLine("Downloading from {0}", feedUrl);
    using (var client = new HttpClient())
    {
        result = await client.GetStringAsync(new Uri(feedUrl, UriKind.Absolute));
        result.Trim();
        System.Diagnostics.Debug.WriteLine("Finished download from {0}", feedUrl);
    }
    return result;
}

它打印第一个字符串,但无法到达第二个字符串,这意味着client.GetStringAsync不会返回。

网址没问题,加载正常。

我的问题是什么?

编辑 2:(现在被删除为无用)

编辑 3:

我正在添加我正在使用的方法,让您知道我的数据流是什么。

页面.xaml

<phone:LongListSelector Grid.Row="1" x:Name="UpcomingResultsList" ItemsSource="{Binding UpcomingMovies}" ItemTemplate="{StaticResource MovieListDataTemplate}" Margin="0, 10, 0, 0" />

UpcomingMovies绑定到这个属性

public List<MovieViewModel> UpcomingMovies
    {
        get
        {
            System.Diagnostics.Debug.WriteLine("UpcomingMovies - Begin");             
            var apiMovies = _serviceRT.FindUpcomingMoviesList().Result; // We get the movies in RT API's format
            var movies = apiMovies.Select(result => new MovieViewModel(result)).ToList();
            System.Diagnostics.Debug.WriteLine("UpcomingMovies - End");
            return movies;
        }
}

_serviceRT.FindUpcomingMoviesList()方法:

/// <summary>
/// Gets a list of upcoming movies.
/// </summary>
/// <returns>MovieSearchResults</returns>
public async Task<MovieSearchResults> FindUpcomingMoviesList()
{
    var url = string.Format(LIST_UPCOMING, ApiKey);
    var jsonResponse = await GetJsonResponse(url);
    var results = Parser.ParseMovieSearchResults(jsonResponse);
    return results;
}

最后,GetJsonResponse()是在问题的开头。

现在,有了完整的数据流,我怎样才能绑定这个属性并仍然完成下载?

4

2 回答 2

1

我预测,在您的调用堆栈中,您正在调用WaitResult从方法Task返回。正如我在博客中描述的那样,这很容易导致死锁。async

发生这种情况是因为await默认情况下会捕获用于恢复该async方法的“上下文”。在您的示例中,这很可能是一个 UI 上下文,它始终只有一个线程(UI 线程)。因此,如果您通过调用Waitor阻塞 UI 线程Result,则该async方法无法重新进入 UI 上下文以完成其执行(并且您最终会等待Task无法完成的 a)。

编辑:

由于您是数据绑定,我建议在此处NotifyTaskCompletion使用该类型(这将很快成为我的 AsyncEx 库的一部分):

public MyViewModel()
{
    UpcomingMovies = NotifyTaskCompletion.Create(LoadUpcomingMoviesAsync());
}

public INotifyTaskCompletion<List<MovieViewModel>> UpcomingMovies { get; private set; }

private async Task<List<MovieViewModel>> LoadUpcomingMoviesAsync()
{
    System.Diagnostics.Debug.WriteLine("UpcomingMovies - Begin");             
    var apiMovies = await _serviceRT.FindUpcomingMoviesList();
    var movies = apiMovies.Select(result => new MovieViewModel(result)).ToList();
    System.Diagnostics.Debug.WriteLine("UpcomingMovies - End");
    return movies;
}

然后你可以INotifyTaskCompletion<T>.Result像这样安全地绑定:

{Binding UpcomingMovies.Result}

请注意,在您加载电影之前,结果将是null您的视图将为空。此外,如果加载电影时出错,您的视图将始终为空。我建议您通过数据绑定到其他INotifyTaskCompletion<T>属性来处理这些情况,例如:

  • {Binding UpcomingMovies.IsCompleted},它将在加载完成时开始false并变为true(成功或错误)
  • {Binding UpcomingMovies.IsSuccessfullyCompleted}true仅当/当加载成功完成时才变为
  • {Binding UpcomingMovies.IsFaulted}true仅当/当加载完成并出现错误时才变为
  • {Binding UpcomingMovies.ErrorMessage},它提取错误消息(null如果没有错误)
于 2013-09-25T23:49:54.307 回答
0

HttpClient 根据调用它的平台有局限性(如果与“大窗口”相比,则与 Windows Phone 上的其他网络相关 API 一样)。也许,这个方法会有所帮助:http: //blogs.msdn.com/b/bclteam/archive/2013/02/18/portable-httpclient-for-net-framework-and-windows-phone.aspx

HttpClientHandler handler = new HttpClientHandler();
httpClient = new HttpClient(handler);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, resourceAddress);
request.Content = streamContent;
if (handler.SupportsTransferEncodingChunked())
{
    request.Headers.TransferEncodingChunked = true;
}
HttpResponseMessage response = await httpClient.SendAsync(request);
于 2013-09-25T23:16:22.873 回答