TAP versus EAP

In Windows Phone 7 waren alle async methods via het event asynchronous pattern wat wil zeggen een method waarmee je de actie start en een event wanneer de operatie compleet is. Je ziet dit bijvoorbeeld op de webclient waar je een dergelijke schrijf wijze zou kunnen gebruiken:

public void GetUrl()
        {
            WebClient client = new WebClient();
            client.DownloadStringCompleted += (s, e) =>
                {
                } ;
            client.DownloadStringAsync(new Uri("http://bing.com"))
        }

Met de release van Windows 8 en de nieuwe C# heeft Microsoft de taal C# uitgebreid met 2 nieuwe keywords die ook een nieuwe async pattern "Task Async Pattern" mogelijk maakt. Dit maakt async programmeren veel eenvoudiger, en dat is ook terug te zien in het platform, aanzienlijk meer API's zijn async geworden. Met TAP komt het er zo uit te zien:

public async void GetUrl()
{
    HttpClient client = new HttpClient();
    using (var data = await client.GetStreamAsync(url))
    {
    }
}

De code wijkt vrijwel niet af van wanneer het niet async zou gebeuren behalve het gebruik van async en await keyword. Het is wel async en vraagt nog wel extra aandacht maar dat laat ik hier even buiten beschouwing.

In Windows Phone 8 is Microsoft niet opnieuw begonnen maar zijn er wel heel veel features uit Windows 8 over geheveld naar de Phone, maar ook heel veel API's zo als deze op Windows Phone 7 bestonden. Voor het asynchroon werken betekend het dat we nu gebruik moeten maken van 2 patronen door elkaar, wat ik zelf niet duidelijker op vind worden.

Gelukkig is het eenvoudig om EAP patroon te wrappen in een een TAP versie . Bij deze de oplossing hoe ik het voor de webclient heb gedaan:

public static class WebClientExtensions
    {
        public static Task<string> DownloadStringAsyncTask(this WebClient client, Uri address)
        {
            TaskCompletionSource<string> completionSource = new TaskCompletionSource<string>();
            client.DownloadStringCompleted += client_DownloadStringCompleted;
            client.DownloadStringAsync(address, completionSource);
            return completionSource.Task;
        }

        private static void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            WebClient client = (WebClient)sender;
            TaskCompletionSource<string> completionSource = (TaskCompletionSource<string>)e.UserState;

            client.DownloadStringCompleted -= client_DownloadStringCompleted;
            try
            {
                completionSource.SetResult(e.Result);
            }
            catch(Exception ex)
            {
                completionSource.SetException(ex);
            }
        }
    }

 

  •   @sandeepchads i needed this last week!
  •   @hrist0ph sorry very busy with work at the moment; but working on a rewrite based on the new sdk but not going as fast as i want
  •   @surface thanks but says i am up to date and want all the goodness of 19H1 on my Surface Go
  •   how often i have to press check for updates to force the may update on my surface go 🐱‍👓? #windowsinsiders
  •   @JenMsft Already available to surface go?
  •   RT @windowsblog: Announcing UI Tests in CI/CD for Desktop App Developers https://t.co/3DK2wzAGlX
  •   RT @mrlacey: I get excited about the simplest (obscure?) things sometimes. Yay, XmlnsDefinitionAttribute is coming to .NET Core 3.0, which…
  •   Why does @slack starts faster on my lightweight mobile device then on my heavy powered Core i7 Laptop?
  •   RT @alexmullans: Azure Artifacts is now priced per GB stored 🥳. No more buying and assigning licenses. Start at https://t.co/JAn6daobLV. F…
  •   @LocalJoost i am the creator :) #sorry