Как написать простой асинхронный метод?
Используя последнюю версию 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 ответа
Я не знаю, можете ли вы пометить Main как async, но вам нужно включить async
Ключевое слово в объявлении любого метода, который использует await
, Например:
public async void DoStuffAsync ()
{
var myClass = new MyClass ();
int result = await myClass.TestAsync ();
}
await
это не то же самое, что Wait()
; делать await
является существенным переписыванием этого метода, и, в частности, влияет на ожидание того, как этот метод выходит к вызывающей стороне. Вы правы в том, что на самом деле он ничего не делает (caveat: return types), кроме как сказать компилятору включить некоторые вещи (как это делают переключатели, например: unsafe
, checked
а также unchecked
если вы думаете об этом) - но учтите: это действительно имеет огромное значение в вашем примере. Если Main()
выходы (и мы не предполагаем других потоков) - вы exe это тост. Ушел. Более не существует. Добавление async
заставляет вас учитывать это только потому, что метод завершается, не означает, что он завершен. Вы действительно не хотите Main()
выход, прежде чем вы будете готовы.
В качестве вторичного эффекта этот переключатель также формализует, что метод может возвращать только такие вещи, как Task
; без переключателя у вас может возникнуть соблазн сделать его асинхронным позже, что может стать серьезным изменением.
Асинхронный метод может иметь тип возврата void или Task. Если возвращаемый тип не имеет значения void, вызывающая сторона может по-прежнему использовать стандартный механизм ожидания, представленный в.Net 4 в методе Main (который не может быть помечен как асинхронный). Вот простой пример:
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"]);
}
}