<Query Kind="Program">
  <Namespace>System.Net</Namespace>
  <Namespace>System.Threading.Tasks</Namespace>
</Query>

// ------------------------------

int Tid () {
    return Thread.CurrentThread.ManagedThreadId;
}

// ------------------------------

(string, int) FetchSync (string name, string url) {
    try {
        Console.WriteLine ("\r\n... [{0}] FetchSync (1): {1}", Tid(), name);

        Uri uri = new Uri (url);
        WebClient webClient = new WebClient ();
    
        string html = webClient.DownloadString (uri);  // !

        Console.WriteLine ("... [{0}] FetchSync (2): got {1} characters from {2}:\r\n{3} ...\r\n", 
            Tid(), html.Length, name, Regex.Replace(html.Substring(0,200), @"\s+", " "));
        return (name, html.Length);

    } catch (Exception ex) {
        Console.WriteLine ("*** [{0}] FetchSync: {1}", Tid(), ex.Message);
        return (name, 0);
    }
}

// ------------------------------

void FetchAsyncOld (string name, string url) {
    Console.WriteLine ("\r\n... [{0}] FetchAsyncOld (1): {1}", Tid(), name);
    
    Uri uri = new Uri (url);
    WebClient webClient = new WebClient ();

    webClient.DownloadStringCompleted += DownloadStringHandler;
    
    webClient.DownloadStringAsync (uri, name);
}

void DownloadStringHandler (Object sender, DownloadStringCompletedEventArgs e) {
    Exception ex = e.Error;
    
    if (ex == null) {
        string html = (string) e.Result;
        string name = (string) e.UserState;
        
        Console.WriteLine ("+++ [{0}] FetchAsyncOld (2): got {1} characters from {2}:\r\n{3} ...\r\n", 
            Tid(), html.Length, name, Regex.Replace(html.Substring(0,200), @"\s+", " "));
		
		return; // (name, html.length) ?
    
    } else {
        Console.WriteLine ("*** [{0}] FetchAsyncOld (2): {1}", Tid(), ex.Message);
		return; // (name, 0) ?
    }
}

// ------------------------------

async Task<(string, int)> FetchAsync (string name, string url) {
    try {
        Console.WriteLine ("\r\n... [{0}] FetchAsyncNew (1): {1}", Tid(), name);

        Uri uri = new Uri (url);
        WebClient webClient = new WebClient ();
    
        //string html = webClient.DownloadString (uri);  // !
        string html = await webClient.DownloadStringTaskAsync (uri); // AsyncDownloadString
    
        Console.WriteLine ("\r\n+++ [{0}] FetchAsync (2): got {1} characters from {2}:\r\n{3} ...\r\n", 
            Tid(), html.Length, name, Regex.Replace(html.Substring(0,200), @"\s+", " "));
        return (name, html.Length);

    } catch (Exception ex) {
        Console.WriteLine ("\r\n*** [{0}] FetchAsync: {1}", Tid(), ex.Message);
        return (name, 0);
    }
}

// ------------------------------

async Task Main () {
    Console.WriteLine ("... [{0}] main0", Tid());

    // ---

    var fs = FetchSync ("Microsoft", "http://www.microsoft.com/");
    Console.WriteLine ("... [{0}] main1 FetchSync: {1}", Tid(), fs);

    // ---

    FetchAsyncOld ("MSDN", "http://msdn.microsoft.com/");    
    Console.WriteLine ("... [{0}] main2 FetchAsyncOld", Tid());
    
    // ---
    
    var fa = FetchAsync ("Bing", "http://www.bing.com"); // await
    Console.WriteLine ("... [{0}]", Tid());
    var fa2 = await fa;  //.Wait (); //
    Console.WriteLine ("... [{0}] main3 FetchAsync: {1}", Tid(), fa2);
	
    Console.WriteLine ("\r\n<enter> to exit\r\n");
    Console.ReadLine ();
}

// ------------------------------