How to write simple async method?
Asked Answered
R

3

17

Using latest CTP5 with async/await keywords, I wrote some code, which apparently cannot compile:

 class Program
    {
        public class MyClass
        {
            async public Task<int> Test()
            {
                var result = await TaskEx.Run(() =>
                    {
                        Thread.Sleep(3000);
                        return 3;
                    });
                return result;
            }
        }

        static void Main(string[] args)
        {
            var myClass = new MyClass();

            //The 'await' operator can only be used in a method or lambda marked with the 'async' modifier error ??!!
            int result = await myClass.Test();

            Console.ReadLine();
        }
    }

What is th reason of "The 'await' operator can only be used in a method or lambda marked with the 'async' modifier error?" (I've selected the line which Visual Studio point me to)

Reunionist answered 21/7, 2011 at 7:42 Comment(0)
M
8

I don't know if you can mark Main as async, but you need to include the async keyword in the declaration of any method that uses await. For example:

public async void DoStuffAsync ()
{
    var myClass = new MyClass ();

    int result = await myClass.TestAsync ();
}
Merely answered 21/7, 2011 at 7:50 Comment(3)
You can declare Main as async, and awaiting anything in it will end your program (assuming you have no other foreground threads running.)Worthy
Duh, I kept thinking that the error is inside my Test method. The Visual Studio should be more informative with this error (like "method Main must async")Reunionist
In the C#5 release, if you mark Main as async, you get an error: "An entry point cannot be marked with the 'async' modifier"Eire
B
4

await is not the same as Wait(); doing an await is a significant re-writing of that method, and in particular affects the expectation of how that method exits to the caller. You are right in that it doesn't actually do much (caveat: return types) except tell the compiler to enable some things (as do switches like unsafe, checked and unchecked if you think about it) - but consider: this actually matters hugely in your example. If Main() exits (and we assume no other threads) - you exe is toast. Gone. No longer exists. Adding async makes you consider that just because the method exits doesn't mean it has finished. You really don't want Main() exiting before you are ready.

As a secondary effect, this switch also formalises that the method can only return things like Task; without the switch, you might be tempted to make it async later, which could be a significantly breaking change.

Beberg answered 21/7, 2011 at 7:52 Comment(1)
@Worthy nice Monty Python there ;pBeberg
E
4

An async method can have a return type of void or Task. If the return type is not void the caller can still use the standard Wait mechanism introduced in .Net 4 inside the Main entry method (which can not be marked async). Here's a simple example:

    static void Main(string[] args)
    {
        string address = "http://api.worldbank.org/countries?format=json";
        Task t = LoadJsonAsync(address);
        // do other work while loading
        t.Wait();

        Console.WriteLine("Hit ENTER to exit...");
        Console.ReadLine();
    }

    private async static Task LoadJsonAsync(string address)
    {
        HttpClient client = new HttpClient();

        HttpResponseMessage response = await client.GetAsync(address);

        // Check that response was successful or throw exception
        response.EnsureSuccessStatusCode();

        // Read response asynchronously as JsonValue and write out top facts for each country
        JsonArray readTask = await response.Content.ReadAsAsync<JsonArray>();
        Console.WriteLine("First 50 countries listed by The World Bank...");
        foreach (var country in readTask[1])
        {
            Console.WriteLine("   {0}, Capital: {1}",
                country.Value["name"],
                country.Value["capitalCity"]);
        }

    }
Eventuality answered 10/5, 2012 at 15:52 Comment(3)
I hate how everyone always uses client.GetAsync as the example. The poster probably knows how to use someone else's async method. How do you write one?? (for example using the Sleep example)Meperidine
What if your async task returns a result? Calling task.wait returns a boolean. How would you go about waiting and then using the returned result? EDIT: Never mind. Task.Result.Wagoner
not sure, but don't you need to start Task t before Wait()-ing for it? t.Start(); t.Wait();Toga

© 2022 - 2024 — McMap. All rights reserved.