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

  •   jeej skype till 22h today..
  •   @VSTS @awscloud @chef @Docker @GooglePlay what are the 10 highest rated widgets?
  •   RT @wpschaub: Over 500 extensions in the VSTS/TFS marketplace https://t.co/pH64ZFRi2J
  •   @mitrik what is difference between code -&gt; files -&gt; history and code -&gt; commits? looks as same? https://t.co/NnA8lk1pTe
  •   @LocalJoost 😵
  •   the moment you need to install ms project....
  •   RT @coolcsh: And we have updated Visual Studio 2017 w/15.3 to for .NET Core 2, https://t.co/2y7Qj07QrB Core 2, .NET Standard 2: https://t.c…
  •   @JenMsft do you know what changed in the latest version of the mail app? the whats new web page is not beeing updated for long time..
  •   new windows sdk! https://t.co/qOlWLICyIB #uwp #uwpdev
  •   @tfsbuck this way doesnt take in consideration it can be set back to "new" because some blocking issues?