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

  •   @MicrosoftHelps fixed it by reinstalling windows but thanks for following up
  •   @JenMsft should have log feedback before resetting windows... but was soo annoyed my pen was not working
  •   @JenMsft surface book with perf base. i reinstalled windows and problem is gone. nasty thing if multi touch doesnt… https://t.co/0vxuKMC6vv
  •   @JenMsft after i installed the FCU multitouch doesnt work. when uninstall driver and reboot it works till next reboot. heared it before?
  •   RT @ruudj: https://t.co/WWSQcFP45k
  •   @maarten_goet @we_are_inspark Nice congrats
  •   nice app showing all windows controls https://t.co/kogun2ws2P
  •   RT @windowsblog: New Map Control features in Windows 10 Fall Creators Update https://t.co/gTLqVAX8HO https://t.co/wuGGF6Yi3Q
  •   RT @LocalJoost: Rather loud explosion sounds at @davesmits #techdaysnl presentation. Who ever was asleep is definitely awake again now 😀
  •   RT @we_are_inspark: 'A Shared HoloLens experience' door @davesmits op @TechDaysNL. Volg zijn sessie over 30 min. in zaal G104-105. https://…