async/await function comparison

前端 未结 3 1456
南旧
南旧 2021-01-16 11:57

I am trying to understand async/await and I am wondering if both methods work identically.If not can you explain why?

       public async Task          


        
3条回答
  •  终归单人心
    2021-01-16 12:15

    Let me point out a few things with your functions:

    public async Task GetClient()
    {
        return await _clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefaultAsync();
    }
    

    This first function is a bit wasteful. Neither async nor await are giving you any benefit. Why do I say that? Well let's just quickly recap the usual benefit of await.

    What await allows you to do is to resume execution of the remainder of the method after the awaited task completes. In your case there is no "remainder of the method" since the return await is the last statement of the method.

    Why is this wasteful? Well, by marking your method asyncyou are basically telling the compiler to generate all the machinery (i.e. state machine) to allow you to resume execution within that same method after each await.

    This machinery is useless in your case since there is nothing after the await to resume executing, so you are better off not marking the method async and instead of return await just do a simple return of the task generated by FirstOrDefaultAsync.

    Doing this will still make the function return and behave asynchronous. Keep in mind that async and await aren't actually what make a function execute asynchronously. async/await simply help setup the machinery to provide "bookmarks" into the various await points in your method so that execution can resume there after each awaited task completes.

    Now let's talk about your second function:

      public Task GetClient2()
      {
         return Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault());
      }
    

    This function is not asynchronous at all. It will execute completely synchronous and not yield the thread at all.

    Even if you did this:

      public async Task GetClient2()
      {
         return await Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault());
      }
    

    The function will still be completely synchronous. Remember, async/await are all about setting up machinery and bookmarks but don't actually have any role on whether the code will execute synchronously or asynchronously.

    So why is this blocking? Because FirstOrDefault() does not return a task, so it means it has to return a Client object. This means it can't return anything until it fully completes the execution of the linq chain. Your Task.FromResult is then just taking this value and wrapping it in a pre-completed task.

    So Just to Recap:

    Only use async/await if you need to resume execution somewhere in the middle of your method.

    Example:

    public async Task IsIntegerIGetFromRemoteServerPostitiveAsync(){
          int result = await GetSomeIntegerAsync();
          Console.WriteLine('Resuming execution of the method');
          return i>0;
    }
    

    If you find that you have a single await and it is the last line of the method then don't use async/await, just return the task instead of awaiting it. This avoids unnecessary overhead.

    Example:

    public Task GetUserInformationAsync(string username){
        var url = $"http://userinfo.com?username={username}"
        return GetSomeJsonFromHttpServerAsync(url); //Assuming this returns Task
    }
    

提交回复
热议问题