Как написать простой асинхронный метод? - PullRequest
17 голосов
/ 21 июля 2011

Используя последнюю версию CTP5 с ключевыми словами async / await, я написал некоторый код, который, по-видимому, не может быть скомпилирован:

 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();
        }
    }

В чем причина? Оператор 'await' можно использовать только в методе илилямбда, помеченная ошибкой модификатора async?(Я выбрал строку, на которую указывает Visual Studio)

Ответы [ 3 ]

8 голосов
/ 21 июля 2011

Я не знаю, можете ли вы пометить Main как асинхронный, но вам нужно включить ключевое слово async в объявление любого метода, который использует await.Например:

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

    int result = await myClass.TestAsync ();
}
4 голосов
/ 21 июля 2011

await не совпадает с Wait(); выполнение await является значительным переписыванием этого метода и, в частности, влияет на ожидание того, как этот метод завершится для вызывающей стороны. Вы правы в том, что на самом деле он не делает много (предостережение: возвращаемые типы), кроме как сказать компилятору включить некоторые вещи (как это делают переключатели, такие как unsafe, checked и unchecked, если вы подумайте об этом) - но подумайте: это действительно имеет значение чрезвычайно в вашем примере. Если Main() выходит (и мы не предполагаем других потоков) - вы exe is toast . Ушел. Более не существует. Добавление async заставляет вас считать, что только метод завершает работу , не означает, что он закончен . Вы действительно не хотите, чтобы Main() выходил до того, как вы будете готовы.

В качестве вторичного эффекта этот переключатель также формализует, что метод может возвращать только такие вещи, как Task; без переключателя у вас может возникнуть желание сделать его асинхронным позже, что может стать серьезным изменением.

3 голосов
/ 10 мая 2012

Асинхронный метод может иметь тип возврата void или Task.Если возвращаемый тип не имеет значения void, вызывающая сторона может по-прежнему использовать стандартный механизм ожидания, представленный в .Net 4 в методе Main entry (который нельзя пометить как асинхронный).Вот простой пример:

    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"]);
        }

    }
...