HttpClient 不会在 Windows Phone 中返回
本文关键字:Phone 返回 Windows HttpClient | 更新日期: 2023-09-27 18:32:59
很简单,这是我的代码:
/// <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:
我正在添加我正在使用的方法,让您知道我的数据流是什么。
Page.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()
在问题的开头。
现在,有了完整的数据流,如何绑定此属性并仍然完成下载?
我预测在您的调用堆栈中,您正在从async
方法返回的Task
上调用Wait
或Result
。正如我在博客上描述的那样,这很容易导致死锁。
发生这种情况是因为默认情况下await
将捕获用于恢复async
方法的"上下文"。在您的示例中,这很可能是一个 UI 上下文,它始终只有一个线程(UI 线程(。因此,如果通过调用 Wait
或 Result
来阻止 UI 线程,则 async
方法无法重新进入 UI 上下文以完成其执行(并且您最终会等待无法完成的Task
(。
编辑:
由于您是数据绑定,我建议在此处使用 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
(
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);