Can't await async extension method

16,761

The error message is pretty clear: the method where you're calling the extension method should be marked as async.

public Task<string> MyExtension(this string s) { ... }

public async Task MyCallingMethod()
{    
    string result = await "hi".MyExtension();
}

Re-reading this part should make much more sense now:

"The 'await' operator can only be used within an async method. "

Share:
16,761
chester89
Author by

chester89

For work projects I use primarily .NET, MySQL and Kafka. I enjoy working with Redis, Postgresql, Prometheus and Elasticsearch. I also have minimal Python skills (wrote several simple scripts), worked on several Scala projects, now in process of learning Go. Sometimes I feel my math skills are not where I would like them and read about algorithms and statistics. I am interested in software development practices and techniques, like unit/acceptance testing, algorithms, data structures and distributed systems.

Updated on June 21, 2022

Comments

  • chester89
    chester89 almost 2 years

    Situation is pretty simple - I wrote an extension method and made it async with return type Task<T>. But when I try to call it using await, compiler throws an error which suggests that the extension method wasn't recognized as async at all. Here's my code:

    public static async Task<NodeReference<T>> CreateWithLabel<T>(this GraphClient client, T source, String label) where T: class
        {
            var node = client.Create(source);
            var url = string.Format(ConfigurationManager.AppSettings[configKey] + "/node/{0}/labels", node.Id);
            var serializedLabel = string.Empty;
            using (var tempStream = new MemoryStream())
            {
                new DataContractJsonSerializer(label.GetType()).WriteObject(tempStream, label);
                serializedLabel = Encoding.Default.GetString(tempStream.ToArray());
            }
            var bytes = Encoding.Default.GetBytes(serializedLabel);
    
            using (var webClient = new WebClient())
            {
                webClient.Headers.Add("Content-Type", "application/json");
                webClient.Headers.Add("Accept", "application/json; charset=UTF-8");
                await webClient.UploadDataTaskAsync(url, "POST", bytes);
            }
    
            return node;
        }
    
    
    var newNode = await client.CreateWithLabel(new Task(), "Task");
    

    Exact error message is this:

    The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'

    Am I doing something wrong or is it a language/compiler limitation?

  • chester89
    chester89 over 10 years
    I see. Will be more attentive next time.
  • noseratio
    noseratio over 10 years
    @dcastro, you may want to change the signature of MyCallingMethod to return a Task, void is only good for async event handlers.
  • dcastro
    dcastro over 10 years
    @Noseratio I disagree, there are plenty of other scenarios where you'd want "fire and forget" behaviour. I will edit my post though, simply because less experienced users might be surprised by the results of async void.
  • noseratio
    noseratio over 10 years
    @dcastro, I disagree too that there are plenty. I'd be interested to learn about any useful scenarios other than async event handlers (which is obviously not the case here).
  • dcastro
    dcastro over 10 years
    Logging, for example. A service may want to fire a method and trigger some business logic, but return to the client asap. You don't always need to wait for the result of a method. Maybe the word "plenty" was a bit too much, but saying that "void is only good for async event handlers" isn't correct either.
  • dcastro
    dcastro over 10 years
    Although being aware of the side effects of async void is very important when going down that road.