Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Windows включает множество асинхронных API, чтобы гарантировать, что ваше приложение остается адаптивным, когда оно работает, что может занять длительное время. В этом разделе описывается использование асинхронных методов в C# или Microsoft Visual Basic.
Асинхронные API позволяют приложению продолжать выполнение, не дожидаясь завершения длительных операций. Например, приложение, скачающее информацию из Интернета, может потратить несколько секунд, ожидая поступления сведений. Если вы используете синхронный метод для получения сведений, приложение блокируется до тех пор, пока метод не возвращается. Приложение не будет реагировать на взаимодействие с пользователем, так как оно кажется нереагируемым, пользователь может стать разочарованным. Предоставляя асинхронные API, Windows помогает обеспечить реагирование приложения на пользователя при выполнении длительных операций.
Большинство асинхронных API в Windows не имеют синхронных аналогов, поэтому необходимо понять, как использовать асинхронные API с C# или Visual Basic в приложении Windows. Здесь показано, как вызывать асинхронные API.
Использование асинхронных API
По соглашению асинхронным методам дают имена, оканчивающиеся на "Async". Обычно вы вызываете асинхронные API в ответ на действие пользователя, например когда пользователь нажимает кнопку. Вызов асинхронного метода в обработчике событий является одним из самых простых способов использования асинхронных API. Здесь мы используем оператор await в качестве примера.
Предположим, у вас есть приложение, в котором перечислены заголовки постов блога из определённого места. Приложение имеет кнопку , которую пользователь щелкает, чтобы получить заголовки. Заголовки отображаются в TextBlock. Когда пользователь нажимает кнопку, важно, чтобы приложение оставалось адаптивным во время ожидания информации с веб-сайта блога. Чтобы обеспечить такую отзывчивость, Windows предоставляет асинхронный метод SyndicationClient.RetrieveFeedAsync для загрузки канала.
В этом примере списки записей из блога получаются путем вызова асинхронного метода SyndicationClient.RetrieveFeedAsync и ожидания результата.
// Put the keyword async on the declaration of the event handler.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
Uri feedUri
= new Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");
try
{
SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);
// The rest of this method executes after await RetrieveFeedAsync completes.
rssOutput.Text = feed.Title.Text + Environment.NewLine;
foreach (SyndicationItem item in feed.Items)
{
rssOutput.Text += item.Title.Text + ", " +
item.PublishedDate.ToString() + Environment.NewLine;
}
}
catch (Exception ex)
{
// Log Error.
rssOutput.Text =
"I'm sorry, but I couldn't load the page," +
" possibly due to network problems." +
"Here's the error message I received: "
+ ex.ToString();
}
}
' Put the keyword Async on the declaration of the event handler.
Private Async Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
Dim client As New Windows.Web.Syndication.SyndicationClient()
Dim feedUri As New Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx")
Try
Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(feedUri)
' The rest of this method executes after the await operation completes.
rssOutput.Text = feed.Title.Text & vbCrLf
For Each item In feed.Items
rssOutput.Text += $"{item.Title.Text}, {item.PublishedDate.ToString()}{vbCrLf}"
Next
Catch ex As Exception
' Log Error.
rssOutput.Text = "I'm sorry, but I couldn't load the page," &
" possibly due to network problems." &
"Here's the error message I received: " &
ex.ToString()
End Try
End Sub
В этом примере есть несколько важных вещей. Во-первых, SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) строка использует оператор await с вызовом асинхронного метода RetrieveFeedAsync. Оператор await можно рассматривать как способ сообщить компилятору, что вы вызываете асинхронный метод, из-за чего компилятор выполняет дополнительную работу, чтобы вам не приходилось делать это самостоятельно. Затем объявление обработчика события содержит ключевое слово async. Необходимо включить это ключевое слово в объявление метода любого метода, в котором используется оператор await .
В этом разделе мы не рассмотрим множество сведений о том, что компилятор делает с оператором await , но давайте рассмотрим, что делает ваше приложение таким образом, чтобы оно было асинхронным и адаптивным. Рассмотрим, что происходит при использовании синхронного кода. Например, предположим, что существует синхронный метод с именем SyndicationClient.RetrieveFeed. (Такого метода не существует, но представьте, что он есть.) Если бы ваше приложение содержало строку SyndicationFeed feed = client.RetrieveFeed(feedUri) вместо SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), выполнение приложения остановилось бы до тех пор, пока не станет доступно возвращаемое значение RetrieveFeed. И пока приложение ожидает завершения метода, оно не может реагировать на другие события, например другое событие Click . То есть приложение будет заблокировано, пока RetrieveFeed не вернется.
Но при вызове client.RetrieveFeedAsyncметод инициирует извлечение и немедленно возвращается. При использовании await с RetrieveFeedAsync приложение временно выходит из обработчика событий. Затем он может обрабатывать другие события во время асинхронного выполнения RetrieveFeedAsync . Это позволяет приложению реагировать на пользователя. Когда RetrieveFeedAsync завершает работу и объект SyndicationFeed становится доступен, приложение по сути снова входит в обработчик событий с того места, где было прервано выполнение, после SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), и завершает выполнение оставшейся части метода.
Преимущество использования оператора await в том, что код почти не отличается от того, как он выглядел бы, если бы вы использовали воображаемый метод RetrieveFeed. Существует способ написания асинхронного кода в C# или Visual Basic без оператора await, но результирующий код, как правило, подчеркивает механику выполнения асинхронно. Это делает асинхронный код сложным для записи, трудно понять и трудно поддерживать. Используя оператор await , вы получаете преимущества асинхронного приложения, не делая код сложным.
Возвращаемые типы и результаты асинхронных API
Если вы перешли по ссылке на RetrieveFeedAsync, возможно, вы заметили, что тип, возвращаемый методом RetrieveFeedAsync, не является SyndicationFeed. Вместо этого тип возвращаемого значения — IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>. Если смотреть на уровне синтаксиса, асинхронный API возвращает объект, который содержит результат. Хотя часто, а иногда и полезно, рассматривать асинхронный метод как объект, к которому можно применить await, оператор await на самом деле применяется к возвращаемому значению метода, а не к самому методу. При применении оператора await возвращается результат вызова GetResult для объекта, возвращаемого методом. В примере SyndicationFeed является результатом GetFeedAsync.GetResult().
При использовании асинхронного метода можно проверить сигнатуру, чтобы увидеть, что вы вернетесь после ожидания значения, возвращаемого из метода. Все асинхронные API возвращают один из следующих типов:
- IAsyncOperation<TResult>
- IAsyncOperationWithProgress<TResult, TProgress>
- IAsyncAction
- IAsyncActionWithProgress<TProgress>
Тип результата асинхронного метода совпадает с параметром TResult типа. Типы без TResult не имеют результата. Вы можете представить результат как пустоту. В Visual Basic процедура Sub эквивалентна методу с типом возвращаемого значения void.
В таблице приведены примеры асинхронных методов и перечислены тип возвращаемого и результирующий тип каждого.
| Асинхронный метод | Тип возвращаемого значения | Тип результата |
|---|---|---|
| SyndicationClient.RetrieveFeedAsync | IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> | SyndicationFeed |
| FileOpenPicker.PickSingleFileAsync | IAsyncOperation<StorageFile> | StorageFile |
| XmlDocument.SaveToFileAsync | IAsyncAction | void |
| InkStrokeContainer.LoadAsync | IAsyncActionWithProgress<UInt64> | void |
| DataReader.LoadAsync | DataReaderLoadOperation— пользовательский класс результатов, реализующий IAsyncOperation<UInt32> | Uint32 |
Note
FileOpenPicker и другие API выбора требуют инициализации дескриптора окна (HWND) в настольных приложениях WinUI 3. Перед вызовом PickSingleFileAsync вызовите WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd), где hwnd поступает из WindowNative.GetWindowHandle(this). См. API выбора WinUI 3, для которых требуется дескриптор окна (HWND).
Асинхронные методы, определенные в .NET для приложений Windows, имеют тип возвращаемого типа Task или Task<TResult>. Методы, возвращающие задачу , похожи на асинхронные методы, возвращающие IAsyncAction. В каждом случае результат асинхронного метода является void. Возвращаемый тип Task<TResult> аналогичен IAsyncOperation<TResult> в том смысле, что результат асинхронного метода при выполнении задачи имеет тот же тип, что и параметр типа TResult.
Обработка ошибок
При использовании оператора await для получения результатов из асинхронного метода можно использовать блок try/catch для обработки ошибок, возникающих в асинхронных методах, так же, как и для синхронных методов. В предыдущем примере выполняется оболочка метода RetrieveFeedAsync и операция await в блоке try/catch для обработки ошибок при возникновении исключения.
Когда асинхронные методы вызывают другие асинхронные методы, любые асинхронные методы, которые приводят к исключению, будут распространяться на внешние методы. Это означает, что можно разместить блок try/catch в самом внешнем методе, чтобы перехватывать ошибки из вложенных асинхронных методов. Опять же, это похоже на то, как вы перехватываете исключения для синхронных методов. Однако в блоке catch нельзя использовать await.
Tip
Начиная с C# 6.0 (.NET Framework 4.6 / Visual Studio 2015), можно использовать ожидание в блоке catch.
Сводка и дальнейшие действия
Шаблон вызова асинхронного метода, который мы показываем здесь, является самым простым для использования при вызове асинхронных API в обработчике событий. Этот шаблон также можно использовать при вызове асинхронного метода в переопределенном методе, который возвращает void или sub в Visual Basic.
При обнаружении асинхронных методов важно помнить:
- По соглашению асинхронным методам дают имена, оканчивающиеся на "Async".
- Любой метод, использующий оператор await , должен иметь объявление с асинхронным ключевым словом.
- Когда приложение находит оператор await , приложение остается адаптивным к взаимодействию с пользователем во время выполнения асинхронного метода.
- Ожидание значения, возвращаемого асинхронным методом, возвращает объект, содержащий результат. В большинстве случаев результат, содержащийся в возвращаемом значении, является полезным, а не самим возвращаемым значением. Тип значения, содержащегося внутри результата, можно найти, просмотрев тип возвращаемого типа асинхронного метода.
- Использование асинхронных API и асинхронных шаблонов часто позволяет повысить скорость реагирования приложения.
В примере в этом разделе выводится текст, который выглядит следующим образом.
Windows Experience Blog
PC Snapshot: Sony VAIO Y, 8/9/2011 10:26:56 AM -07:00
Tech Tuesday Live Twitter #Chat: Too Much Tech #win7tech, 8/8/2011 12:48:26 PM -07:00
Windows 7 themes: what's new and what's popular!, 8/4/2011 11:56:28 AM -07:00
PC Snapshot: Toshiba Satellite A665 3D, 8/2/2011 8:59:15 AM -07:00
Time for new school supplies? Find back-to-school deals on Windows 7 PCs and Office 2010, 8/1/2011 2:14:40 PM -07:00
Best PCs for blogging (or working) on the go, 8/1/2011 10:08:14 AM -07:00
Tech Tuesday – Blogging Tips and Tricks–#win7tech, 8/1/2011 9:35:54 AM -07:00
PC Snapshot: Lenovo IdeaPad U460, 7/29/2011 9:23:05 AM -07:00
GIVEAWAY: Survive BlogHer with a Sony VAIO SA and a Samsung Focus, 7/28/2011 7:27:14 AM -07:00
3 Ways to Stay Cool This Summer, 7/26/2011 4:58:23 PM -07:00
Getting RAW support in Photo Gallery & Windows 7 (…and a contest!), 7/26/2011 10:40:51 AM -07:00
Tech Tuesdays Live Twitter Chats: Photography Tips, Tricks and Essentials, 7/25/2011 12:33:06 PM -07:00
3 Tips to Go Green With Your PC, 7/22/2011 9:19:43 AM -07:00
How to: Buy a Green PC, 7/22/2011 9:13:22 AM -07:00
Windows 7 themes: the distinctive artwork of Cheng Ling, 7/20/2011 9:53:07 AM -07:00
Windows developer