Search code examples
c#asynchronousasync-awaitctp

c# Can a "task method" also be an "async" method?


I'm trying to get the hand of the new async CTP stuff and I'm probably confusing myself here.. I can have this "task method", with no problem:

    public static Task<String> LongTaskAAsync() {
        return Task.Run(() => {
            return("AAA");
            });
        }

But what if I need the task to execute another task, can I mark it as "async" and use "await"? I tried this:

public async static Task<String> LongTaskAAsync() {
        await Task.Delay(2000);
        return Task.Run(() => {
            return("AAA");
            });
        }

But then mysteriously get this compiler error: Since this is an async method, the return expression must be of type 'string' rather than Task<string>

What am I missing here?


Solution

  • You may want to read my async/await intro post.

    Return values from async methods are wrapped in a Task<TResult>. Likewise, await unwraps those return values:

    public static async Task<String> LongTaskAAsync() {
      await Task.Delay(2000);
      return await Task.Run(() => {
        return("AAA");
      });
    }
    

    The reasoning behind this is described in my Async "Why Do the Keywords Work That Way" Unofficial FAQ.

    P.S. You can also use Task.FromResult for simple tests like this.

    Edit: If you want to create and return the Task object itself, then the method should not be async. One somewhat common pattern is to have a public non-async method that calls the async portion only if necessary.

    For example, some kind of asynchronous cache - if the object is in the cache, then return it immediately; otherwise, asynchronously create it, add it to the cache, and return it (this is example code - not thread-safe):

    public static Task<MyClass> GetAsync(int key)
    {
      if (cache.Contains(key))
        return Task.FromResult(cache[key]);
      return CreateAndAddAsync(key);
    }
    
    private static async Task<MyClass> CreateAndAddAsync(int key)
    {
      var result = await CreateAsync(key);
      cache.Add(key, result);
      return result;
    }