locked
Async method lacks await RRS feed

  • Question

  • Hi,

    I've recently started looking into the asynchronous helper methods async and await. But it feels that I'm missing something.

    Have these two methods:

            private async void button2_Click(object sender, EventArgs e)
            {           
                //Async
                var tasks = new List<Task<List<int>>>();
                tasks.Add(TestAsync());
                tasks.Add(TestAsync());
                tasks.Add(TestAsync());
                var test = await Task.WhenAll(tasks);
            }
    //Warning message: This async method lacks await operator private async Task<List<int>> TestAsync() { List<int> ret = new List<int>(); for (int i = 0; i < 10000000; i++) { if (i % 2 == 0 && i / 3 == 1) ret.Add(i); } return ret; }

    But this seems to run in the same thread and not asynchronously. Where should the await operator be stated in the "TestAsync" method?

    Wednesday, January 14, 2015 1:00 PM

Answers

  • Hi,

    Of course, if you declare "async" for a method, you have to call "await" somewhere in it, otherwise the method is done synchronously.

    For your case, you don't need to mark the "TestAsync" as async. In order to make your method really asynchronous, you should write it like this instead :

    private Task<List<int>> TestAsync()
    {
      return Task.Run(() =>
      {
        List<int> ret = new List<int>();
        for (int i = 0; i < 10000000; i++)
        {                
          if (i % 2 == 0 && i / 3 == 1)
            ret.Add(i);
        }
        return ret;
      });
    }

    You could do it with an "async" keyword but it has no interest :

    private async Task<List<int>> TestAsync()
    {
      Task<List<int>> tsk = Task.Run(() =>
      {
        List<int> ret = new List<int>();
        for (int i = 0; i < 10000000; i++)
        {                
          if (i % 2 == 0 && i / 3 == 1)
            ret.Add(i);
        }
        return ret;
      });
      await tsk;
      return tsk.Result;
    }

    In fact, the "asynchronous part" starts when the method with "await" is called. All the code called before is synchronous. And if you don't call the method with ".ConfigureAwait(false)", then all the code after the "await call" is also synchronous. Anyway, did you take a look at this link?



    Philippe


    • Edited by PhGr_ Wednesday, January 14, 2015 1:18 PM
    • Marked as answer by AsusT9 Wednesday, January 14, 2015 3:38 PM
    Wednesday, January 14, 2015 1:13 PM

All replies

  • Hi,

    Of course, if you declare "async" for a method, you have to call "await" somewhere in it, otherwise the method is done synchronously.

    For your case, you don't need to mark the "TestAsync" as async. In order to make your method really asynchronous, you should write it like this instead :

    private Task<List<int>> TestAsync()
    {
      return Task.Run(() =>
      {
        List<int> ret = new List<int>();
        for (int i = 0; i < 10000000; i++)
        {                
          if (i % 2 == 0 && i / 3 == 1)
            ret.Add(i);
        }
        return ret;
      });
    }

    You could do it with an "async" keyword but it has no interest :

    private async Task<List<int>> TestAsync()
    {
      Task<List<int>> tsk = Task.Run(() =>
      {
        List<int> ret = new List<int>();
        for (int i = 0; i < 10000000; i++)
        {                
          if (i % 2 == 0 && i / 3 == 1)
            ret.Add(i);
        }
        return ret;
      });
      await tsk;
      return tsk.Result;
    }

    In fact, the "asynchronous part" starts when the method with "await" is called. All the code called before is synchronous. And if you don't call the method with ".ConfigureAwait(false)", then all the code after the "await call" is also synchronous. Anyway, did you take a look at this link?



    Philippe


    • Edited by PhGr_ Wednesday, January 14, 2015 1:18 PM
    • Marked as answer by AsusT9 Wednesday, January 14, 2015 3:38 PM
    Wednesday, January 14, 2015 1:13 PM
  • >>But this seems to run in the same thread and not asynchronously

    Just marking a method with async modifier doesn't make it run on another thread. The async keyword simply enables the await keyword in the method and changes how method results are handled. That’s all the async keyword does: http://blog.stephencleary.com/2012/02/async-and-await.html

    >>Where should the await operator be stated in the "TestAsync" method?

    Since you can only await Tasks, there is no reason to mark a method as async at all if you don't intend to call any method that returns Task or Task<T> from within the method.

    You could put your loop inside a Task to run it on a background thread if you want:

        private async Task<List<int>> TestAsync() {
          List<int> ret = new List<int>();
          await Task.Run(() =>
          {
            for (int i = 0; i < 10000000; i++) {
              if (i % 2 == 0 && i / 3 == 1)
                ret.Add(i);
            }
          });
          return ret;
        }

    Then your application will remain responsive during the time it takes for the for loop to complete.

    Hope that helps.

    Please remember to mark helpful posts as answer and/or helpful.

    Wednesday, January 14, 2015 1:35 PM