Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие КНЕУ.doc
Скачиваний:
24
Добавлен:
07.03.2016
Размер:
3.9 Mб
Скачать

11.2. Асинхронне уведення-виведення

Клас Stream (і, відповідно, FileStream) підтримує два способи виконання операцій уведення-виведення: синхронний і асинхронний. За умовчанням файли відкриваються в синхронному режимі, тобто подальші оператори виконуються тільки після завершення операцій введення-виведення. Для тривалих файлових операцій ефективніше виконувати уведення-виведення асинхронно, в окремому потоці виконання. При цьому в первинному потоці можна виконувати інші операції.

Для асинхронного уведення-виведення необхідно відкрити файл в асинхронному режимі, для цього використовується відповідний варіант перевантаженого конструктора. Асинхронна операція введення ініціюється за допомогою методу BeginRead. Окрім характеристик буфера, в який виконується введення, в цей метод передається делегат, який задає метод, що виконується після завершення введення.

Цей метод може ініціювати обробку отриманої інформації, відновити операцію читання або виконати будь-які інші дії, наприклад, перевірити успішність введення і повідомити про його завершення. Зазвичай в цьому методі викликається метод EndRead, який завершує асинхронну операцію.

Аналогічно виконується і асинхронне виведення. У лістингу 11.2 приведений приклад асинхронного читання з файлу великого об'єму і паралельного виконання діалогу з користувачем.

Лістинг 11.2. Асинхронне введення

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

namespace examp75

{

class Demo

{

FileStream f;

byte[] buf = new byte[66666666];

AsyncCallback callback;

public void UserInput() // діалог з користувачем

{

string s;

do

{

Console.WriteLine("Введіть рядок. Enter для завершення ");

s = Console.ReadLine();

} while (s.Length != 0);

}

public void OnCompletedRead(IAsyncResult ar) // 1

{

int bytes = f.EndRead(ar);

Console.WriteLine("Налічено " + bytes);

}

public void AsyncRead()

{

try

{

f = new FileStream("1.txt", FileMode.Open,

FileAccess.Read, FileShare.Read, buf.Length, true); // 2

callback = new AsyncCallback( OnCompletedRead ); //3

f.BeginRead( buf, 0, buf.Length, callback, null ); // 4

}

catch (Exception e)

{

Console.WriteLine("Error " + e.Message);

}

}

}

class Program

{

static void Main(string[] args)

{

Demo d = new Demo();

d.AsyncRead();

d.UserInput();

}

}

}

Для зручності сприйняття операції читання з файлу і діалогу з користувачем оформлені в окремий клас Demo.

Метод OnCompletedRead (оператор 1) повинен отримувати один параметр стандартного типу IAsyncResult, що містить відомості про завершення операції, які передаються в метод EndRead.

Файл відкривається в асинхронному режимі, про це говорить значення true останнього параметра конструктора (оператор 2). У операторові 3 створюється екземпляр стандартного делегата AsyncCallback, який ініціалізувався методом OnCompletedRead.

За допомогою цього делегата метод OnCompletedRead передається в метод BeginRead (оператор 4), який створює окремий потік, починає асинхронне введення і повертає управління в потік, що викликає. Зворотний виклик методу OnCompletedRead відбувається при завершенні операції введення. При достатньо довгому файлі verybigfile можна переконатися, що запрошення до введення в методі UserInput видається раніше, ніж повідомлення про завершення операції введення з методу OnCompletedRead.

Приклад, приведений в лістингу 11.2, максимально спрощений для демонстрації методів BeginRead і EndRead, тому в ньому немає необхідних перевірок наявності файлу, успішності читання і так далі.