namespace WebReader
{
public partial class frm_Main : Form
{
public frm_Main()
{
InitializeComponent();
}
private void frm_Main_Load(object sender, EventArgs e)
{
using var clt= new HttpClient();
var res = clt.GetAsync("https://daera.net/dmoon/testfile.txt");
while (true)
{
if (res.IsCompletedSuccessfully)
{
var msg = clt.GetStringAsync("https://daera.net/dmoon/testfile.txt");
MessageBox.Show(msg.ToString());
break;
}
}
}
}
}
This code is supposed to show the contents of the text file https://daera.net/dmoon/testfile.txt
, but it shows a message box with some technical information regarding clt object and nothing else.
What am I doing wrong? I am using Visual Studio 2019.
As I said in the comments, the GetStringAsync()
call is also asynchronous and returns a Task<String>
.
You have several options for synchronizing these tasks with your main program.
while(true)
loop checking for IsCompletedSuccessfully
. This is not recommended at all, because it eats your resources doing nothing.Task.Wait()
. This is a blocking call and what you're looking for. (Edited: it's closer to your original loop without eating resources; but you probably don't want to block your form until the HTTP call ends, which would make your program unresponsive. Look for option 3 or Task.ContinueWith()
)await
as in @Joel's answer (*).This is your code, using option 1 for GetAsync()
(again, not recommended) and option 2 for GetStringAsync()
.
namespace WebReader
{
public partial class Program
{
static void Main ()
{
using var clt= new HttpClient();
var res = clt.GetAsync("https://daera.net/dmoon/testfile.txt");
while (true)
{
if (res.IsCompletedSuccessfully)
{
var responseTask = clt.GetStringAsync("https://daera.net/dmoon/testfile.txt");
responseTask.Wait();
Console.WriteLine(responseTask.Result.ToString());
break;
}
}
}
}
}
(*) More technical. Asynchronous functions run in a separate Task (think of it as a separate thread or lightweight process, but several tasks may actually reuse the same thread). When you use await
for calling an async function B from a function A, the caller (A) won't execute the instructions following the call until the asynchronous task (and the callee, B) completes; but A will immediately return to its own caller. That is, the caller (A) will also be asynchronous (and that's the reason for the mandatory async
keyword). If A is your main() function, it may return to the .NET runtime (the Windows Forms loop, etc), while the asynchronous tasks are still running.
Edited. As been said, using await
is easier, provided you can tag your Main()
function as async
. I don't know if you can do that with your version of Windows Forms (read @Mixin comment), but you can take this console application code (which works) as an example:
namespace WebReader
{
public partial class Program
{
public static async Task Main ()
{
using var clt = new HttpClient();
var response = await clt.GetAsync("https://daera.net/dmoon/testfile.txt");
// You should check response.StatusCode here
var responseContent = await clt.GetStringAsync("https://daera.net/dmoon/testfile.txt");
Console.WriteLine(responseContent.ToString());
}
}
}
As an option, you could write exactly the same code in a separate function, just like this one, and call this function from your actual frm_Main()
using Task.Wait(yourAsyncFunction())
.