Это действительно сложно, потому что XmlReader
не предоставляет никакого асинхронного интерфейса.
Я не совсем уверен, насколько асинхронно ведет себя BeginRead
, когда вы просите его прочитать 0 байтов - он может также немедленно вызвать обратный вызов и затем заблокировать при вызове Read
. Это может быть то же самое, что прямой вызов Read
и планирование следующего Read
в пуле потоков, например, с использованием QueueWorkItem
.
Может быть лучше использовать BeginRead
в сетевом потоке для чтения данных, например, фрагментами по 10 КБ (пока система ожидает данные, вы не заблокируете какой-либо поток). Когда вы получите чанк, вы скопируете его в какой-нибудь локальный MemoryStream
, а ваш XmlReader
будет читать данные из этого MemoryStream
.
Это все еще имеет проблему - после копирования 10 КБ данных и вызова Read
несколько раз последний вызов заблокируется. Тогда вам, вероятно, потребуется скопировать меньшие порции данных, чтобы разблокировать ожидающий вызов на Read
. Как только это будет сделано, вы можете снова начать новый вызов BeginRead
для асинхронного чтения большей части данных.
Честно говоря, это звучит довольно сложно, поэтому мне очень интересно, если кто-нибудь придумает лучший ответ. Тем не менее, он дает вам, по крайней мере, некоторые гарантированные асинхронные операции, которые занимают некоторое время и в то же время не блокируют никакие потоки (что является основной целью асинхронного программирования).
( Примечание: Вы можете попытаться использовать F # асинхронные рабочие процессы , чтобы написать это, потому что они делают асинхронный код намного проще. Метод, который я описал, будет хитрым даже в F #, хотя )