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

  •   @JenMsft @LocalJoost @vinothrajendran not sure if related but when i click update &amp; restart my machine restarts, bu… https://t.co/4muU3d7aGG
  •   RT @natfriedman: Today(!) we’re thrilled to announce unlimited free private repos for all GitHub users, and a new simplified Enterprise off…
  •   @rendyfaqot hi, Sorry to hear. There been some breaking change in the VSTS api... didn't had time yet on fixing tho… https://t.co/lZBMHu4CPf
  •   RT @ameijers: The Global MR Bootcamp was a blast! The biggest #mixedreality event in the world! And all made possible by you the community.…
  •   RT @LocalJoost: Attendants 'working at my Immersive Headset Development workshop at #GlobalMRBootcamp https://t.co/NaNtyO5Ocj
  •   Why do i always decide to change the whole approach of a session the evening before?
  •   @JenMsft @bing it's not working so well for high speed or the distance is a problem https://t.co/KE1kE0wQuF
  •   @danhellem @mmanela Nice!
  •   RT @danhellem: Check out the new changes for the Azure Boards work item tracking experiences in Visual Studio 2019 https://t.co/c4l0rQky1o…
  •   @LocalJoost you put a AAAA battery in your surface pro itself? or the pen?