804
Глава.28 .Асинхронные.операции.ввода-вывода
асинхронные функции в FCL
Лично мне модель асинхронных функций очень симпатична, потому что ее до-
вольно легко освоить, она проста в использовании и поддерживается многими
типами библиотеки FCL. Асинхронные функции сразу видны в коде, потому что
по действующим соглашениям имя метода снабжается суффиксом
Async
. В FCL
многие типы, предоставляющие операции ввода-вывода, также предоставляют
методы
XxxAsync
. Несколько примеров
1
:
Все производные от
System.IO.Stream
классы предоставляют методы
ReadAsync
,
WriteAsync
,
FlushAsync
и
CopyToAsync
.
Все производные от
System.IO.textReader
классы предоставляют методы
ReadAsync
,
ReadLineAsync
,
ReadToEndAsync
и
ReadBlockAsync
. Классы, произ-
водные от
System.IO.TextWriter
, предоставляют методы
WriteAsync
,
Write-
LineAsync
и
FlushAsync
.
Класс
System.Net.Http.HttpClient
предоставляет методы
GetAsync
,
Get-
StreamAsync
,
GetByteArrayAsync
,
PostAsync
,
PutAsync
,
DeleteAsync
и др.
Все производные от
System.Net.WebRequest
классы (включая
FileWebRequest
,
FtpWebRequest
и
HttpWebRequest
) предоставляют методы
GetRequestStreamAsync
и
GetResponseAsync
.
Класс
System.Data.SqlClient.SqlCommand
предоставляет методы
Exe-
cuteDbDataReaderAsync
,
ExecuteNonQueryAsync
,
ExecuteReaderAsync
,
ExecuteScalarAsync
и
ExecuteXmlReaderAsync
.
Инструменты (такие, как
SvcUtil exe
), создающие типы представителей для веб-
служб, также генерируют методы
XxxAsync
.
Программистам с опытом использования предыдущих версий .NET Framework
могут быть известны другие модели асинхронного программирования — как, напри-
мер, модель, использовавшая методы
BeginXxx
и
EndXxx
в сочетании с интерфейсом
IAsyncResult
. Также имеется событийная модель, использовавшая методы
XxxAsync
(не возвращающие объекты
Task
) с вызовами методов обработчиков событий при
завершении асинхронных операций. Эти две модели асинхронного программиро-
вания теперь считаются устаревшими, и вместо них рекомендуется использовать
новую модель с объектами
Task
.
Просматривая описания классов FCL, можно заметить, что у некоторых классов
нет методов
XxxAsync
, а вместо них предоставляются методы
BeginXxx
и
EndXxx
.
В основном это объясняется тем, что у компании Microsoft не было времени для
1
Методы WinRT поддерживают те же соглашения об именах и возвращают интерфейс
IAsyncInfo. К счастью, .NET Framework поддерживает методы расширения, которые пре-
образуют IAsyncInfo в Task. Дополнительная информация об использовании асинхронных
WinRT API с асинхронными функциями приведена в главе 25.
805
Асинхронные.функции.в.FCL
обновления этих классов новыми методами. В будущем эти классы будут дорабо-
таны, и в них появится полноценная поддержка новой модели. А до того времени
можно воспользоваться вспомогательным методом, адаптирующим старую модель
BeginXxx
/
EndXxx
для новой модели на базе
Task
.
Ранее я приводил код клиентского приложения, которое передает запрос по
именованному каналу. Пора привести серверную сторону этого кода.
private static async void StartServer() {
while (true) {
var pipe = new NamedPipeServerStream(c_pipeName, PipeDirection.InOut, 1,
PipeTransmissionMode.Message, PipeOptions.Asynchronous |
PipeOptions.WriteThrough);
// Асинхронный прием клиентского подключения.
// ПРИМЕЧАНИЕ: NamedPipeServerStream использует старую модель
// асинхронного программирования.
// Я преобразую ее к новой модели Task при помощи метода
// FromAsync класса TaskFactory.
await Task.Factory.FromAsync(pipe.BeginWaitForConnection,
pipe.EndWaitForConnection, null);
// Начало обслуживания клиента; управление возвращается немедленно,
// потому что операция выполняется асинхронно.
ServiceClientRequestAsync(pipe);
}
}
В классе
NamedPipeServerStream
определены методы
BeginWaitForConnection
и
EndWaitForConnection
, но еще не определен метод
WaitForConnectionAsync
.
Ожидается, что этот метод будет добавлен в будущей версии FCL. Впрочем, как
видно из предыдущего кода, я вызываю метод
FromAsync
класса
TaskScheduler
,
передаю ему имена методов
BeginXxx
и
EndXxx
, а метод
FromAsync
создает объект
Task
, который является «оберткой» для этих методов. Теперь объект
Task
можно
использовать с оператором
await
1
.
Для старой событийной модели программирования в FCL нет вспомогатель-
ных методов, адаптирующих эту модель к новой модели на базе
Task
, поэтому вам
придется программировать их вручную. Следующий код показывает, как упако-
вать объект
WebClient
(использующий событийную модель программирования)
с объектом
TaskCompletionSource
, чтобы для него можно было вызывать
await
в асинхронной функции.
private static async Task AwaitWebClient(Uri uri) {
// Класс System.Net.WebClient поддерживает событийную модель
1
У метода FromAsync класса TaskScheduler имеются перегруженные версии, получающие
IAsyncResult, а также перегруженные версии, получающие делегатов для методов BeginXxx
и EndXxx. По возможности постарайтесь избегать версии с IAsyncResult, потому что они
менее эффективны.
продолжение
806
Do'stlaringiz bilan baham: |