I just following a sample in calling HttpClient in sync mode, it works fine in a Console application.
However, when I move it to a wpf application, the program hanged without any return.
I try to isolate the problem by building a separate class to handle a dummy request to visit www.google.com.
It seems that the application hang in calling client.GetAsync, may I know if there has any thing need to be changed from console application to wpf in this case?
Please find the source of both the console application and wpf as below,
Console application - works fine:
using System;
using System.Threading.Tasks;
using System.Net.Http;
namespace ca03
{
static class action
{
static async Task<string> DownloadPageAsync()
{
// ... Target page.
string page = "http://www.google.com/";
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// ... Read the string.
string result = await content.ReadAsStringAsync();
// ... Display the result.
if (result != null &&
result.Length >= 50)
{
Console.WriteLine(result.Substring(0, 50) + "...");
}
return result;
}
}
public static string goDownload()
{
Task<string> x = DownloadPageAsync();
string result = x.Result;
return result;
}
}
class Program
{
static void Main(string[] args)
{
string data = action.goDownload();
Console.WriteLine(data);
Console.ReadLine();
}
}
}
WPF application: (just a plain project with a button added) - hang in GetAsync
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Net.Http;
namespace wpf02
{
static class action
{
static async Task<string> DownloadPageAsync()
{
// ... Target page.
string page = "http://www.google.com/";
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// ... Read the string.
string result = await content.ReadAsStringAsync();
return result;
}
}
public static string goDownload()
{
Task<string> x = DownloadPageAsync();
string result = x.Result;
return result;
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
string data = action.goDownload();
Console.WriteLine(data);
}
}
}
This line is the problem:
string result = x.Result;
When you use the Result
property, that blocks the current thread until the task has completed. That's a problem when your continuations are meant to run on the same thread...
Basically, there's no point in your goDownload
method - just change your DownloadPageAsync
method to be public, then change your button_Click
method to also be async so you can await the result:
private async void button_Click(object sender, RoutedEventArgs e)
{
string data = await action.DownloadPageAsync();
Console.WriteLine(data);
}
See more on this question at Stackoverflow