0

I have a function which acquires the client-side source code of a site, but sadly it's not an async function :/ So, I created an async version of the function, and it's returning unexpected results. Here's the safe and working one

public static string GetWebSource(Uri url)
    {
        WebClient client = new WebClient();

        Stream stream = client.OpenRead(url);
        StreamReader reader = new StreamReader(stream);
        string source = reader.ReadToEnd();
        stream.Close();
        reader.Close();

        return source;
    }

It returns the source code as expected, cool, great, except it's not async so it messes up the UI. Here is the async version

public async static Task<string> GetWebSourceAsync(Uri url)
    {
        WebClient client = new WebClient();

        Stream stream = await client.OpenReadTaskAsync(url);
        StreamReader reader = new StreamReader(stream);
        string source = await reader.ReadToEndAsync();
        stream.Close();
        reader.Close();

        return source;
    }

Except this function returns "System.Threading.Tasks.Task`1[System.String]" I googled for a solution and I found Microsoft solution, they don't know how to make good explanations or straight solutions so that was a fraud.

Here is my code to print the value out

string source = GetWebSourceAsync(new Uri("http://checkip.dyndns.org/")).ToString();
        source = source.Replace("<html><head><title>Current IP Check</title></head><body>Current IP Address: ", "").Replace("</body></html>", "");
        Console.Write(source);

So how do I make it display the string? .ToString() extension method doesn't seem to work :/ Regards, TuukkaX.

Yytsi
  • 424
  • 1
  • 5
  • 14

3 Answers3

3

You need to use await on async methods to unwrap the task to T (in your case a string). Else you'll just get the Task<string> back.

string source = await GetWebSourceAsync(new Uri("http://checkip.dyndns.org/"));
source = source.Replace("<html><head><title>Current IP Check</title></head><body>Current IP Address: ", "").Replace("</body></html>", "");
Console.Write(source);
Karl-Johan Sjögren
  • 16,544
  • 7
  • 59
  • 68
  • worth noting that the consuming method needs to be `async` as well to use `await` – Jonesopolis Jul 09 '15 at 18:22
  • True that, but he had already gotten that part right in his own code so I didn't feel the need to tell him that again. – Karl-Johan Sjögren Jul 09 '15 at 18:25
  • Umm, I'm using that function in my console application, the main void can't be async. I tried making a new function that would be async and would return string with the source on it, it doesn't allow me to make the function async because it returns string :/ – Yytsi Jul 09 '15 at 18:28
  • 1
    Yes `Main()` can't be async in C# (for now at least) but if you wrap your code in a `Task.Run()` with an async task it will work. See http://stackoverflow.com/a/24601591/547640 for a sample. – Karl-Johan Sjögren Jul 09 '15 at 18:31
  • I could create an global string outside the main function and I could set the global string value to the source gained from the 'getsourceAsync' function. But isn't there another way? – Yytsi Jul 09 '15 at 18:31
  • 1
    sounds like you need an intro course on `async`/`await`. – Jonesopolis Jul 09 '15 at 18:32
  • If you set a global string value from the task without awaiting it it would almost never have completed before you try to read it so that wouldn't work. The easiest solution, since you are in a console app anyway, would be to just use `WebClient.DownloadString(Uri)` and forget about the async stuff. – Karl-Johan Sjögren Jul 09 '15 at 18:33
  • Oh didn't see that one before I posted my comment :O thanks for the solution! – Yytsi Jul 09 '15 at 18:34
1

It's an async function, so it returns a Task<string>. You should await it, or wait for the Task to finish.

zmbq
  • 38,013
  • 14
  • 101
  • 171
0

What I would do, add .Result at the end of the line calling the method:

string source = GetWebSourceAsync(new Uri("http://checkip.dyndns.org/")).Result;

'Result' takes whatever type there is in the T out. In your case, it makes the Task<string> into a string.

Rob Koch
  • 1,523
  • 3
  • 18
  • 26