Synchroon werken met Tasks

Wanneer je interfaces ontwerpt leg je in de interface vaak al vast of deze asynchroon werkt of synchroon werkt. Neem de volgende volgende Task Async Pattern implementatie, het patroon dat voor de keywords async en await word gebruikt:

public interface ITAPProvider
{
    Task<string> GetStringFromUrl(string url)
} 

 Een mogelijke implementatie die daar bij hoort kan er als volgt uitzien:

public class HttpClientProvider : ITAPProvider
{
    public async Task<string> GetStringFromUrl(string url)
    {
       HttpClient client = new HttpClient();
       string result = await client.GetStringAsync(url);
       return result;
    }
}

Wat interessant is in deze code dat er niet een Task<string> word gereturneed maar een string. De compiler pakt dit zelf in een Task. Dit gebeurd omdat er de keyword async in de method staat.
Wanneer je nu geen await gebruikt in de body gaat de compiler echter waarschuwingen geven. Neem deze code:

public class HttpClientProvider : ITAPProvider
{
   public async Task<string> GetStringFromUrl(string url)
   {
      return "test";
   }
}

Levert deze compiler warning op:

Nu kan je deze negeren, maar zelf vind ik dat niet erg fijn. Nu kan je ook het async keyword weghalen en zelf een task terug geven 

public class HttpClientProvider : ITAPProvider
{
   public Task<string> GetStringFromUrl(string url)
   {
            return Task.Run(() => "test");
   }
}

Echter word met deze code de string return echt weer async en een hoop overbodige overhead toegevoegd wat de code traag maakt. Gelukkig is er ook een andere oplossing. Er is een class  TaskCompletionSource en hiermee kan je een string inpakken in een task wat zonder al te veel overhead gebeurd (er gaat namelijk geen async actie lopen). Dat zou er zo uitzien:

public Task<string> GetStringFromUrl(string url)
{
    return Task.FromResult("test");
}

Wanneer je toch niet helemaal direct het resultaat hebt maar niet met await kan werken is er nog een andere oplossing:

public Task<string> GetStringFromUrl(string url)
{
    TaskCompletionSource<string> taskResult = new TaskCompletionSource<string>();
    taskResult.SetResult("test");
    return taskResult.Task;

 

 Nu ben je van de compiler warning af en introduceer je geen extra overhead door gebruik van een losse task

  •   RT @VisualStudio: In this episode, we're joined by Kasey Uhlenhuth (@kuhlenhuth) who shows some of the refactoring features available in Vi…
  •   @VSTS problems with build queues atm?
  •   RT @donasarkar: Hi #WindowsInsiders we have released Build 17713 to the Fast ring! This build has several new features we think IT Pros wil…
  •   RT @maryjofoley: ICYMI, another Windows 10 on ARM PC is available: Lenovo Miix 630 ARM-based 2-in-1 Windows tablet goes on sale for $900 ht…
  •   the moment you have a meeting and skype for business protocol handller is lost again ...
  •   @LocalJoost Surface Go vanaf 27 augustus te bestellen?
  •   tnx @VistaHypotheken https://t.co/qFoQS6mQ63
  •   @gotheap based on the link i understand they should show up after a build as well? i only see them for the test on… https://t.co/XadwWJjIAM
  •   @panos_panay will the surface go with lte have gps? i need a new device to run my own app for navigation while flying around
  •   @aaronbjork @IoannisKarlis @Jira @VSTS and replace delivery plans with the feature timeline extension. that is really helpful!