Дополнительные темы - 11 Февраля 2010 - Лекции
Пятница, 09.12.2016, 08:42
Приветствую Вас Гость | RSS

Лекции

Меню сайта
Форма входа
Категории раздела
ТАУ (Теория автоматического управления) [31]
лекции по ТАУ
Экология [151]
учебник
Бухгалтерский учет и налогообложение в строительстве [56]
Дементьев А.Ю. - Практическое пособие
Психология [104]
Пип
информатика [80]
с# Карли Ватсон
современные стулья [0]
новинки
Поиск
Главная » 2010 » Февраль » 11 » Дополнительные темы
00:45
Дополнительные темы
Дополнительные темы
В этом разделе мы рассмотрим вопрос, касающийся наблюдения за состоянием
файловой системы, в результате которого приложение сможет получать уведомле-
ние об происходящих изменениях, а также асинхронный доступ к файлам, который
позволяет загружать большие файлы на фоне продолжения выполнения приложе-
нием других процессов.
Наблюдение за состоянием файловой структуры
Иногда в задачу приложения входит нечто большее, чем просто чтение и запись
файлов, хранящихся в файловой системе, и оказывается важным определить мо-
мент, когда в структуру файлов и директорий вносятся изменения. .NET Framework
существенно облегчает создание приложений, которые могут выполнять постав-
ленную задачу.
Класс, ПОЗВОЛЯЮЩИЙ Нам добиваться ЭТОГО, называется FileSystemWatcher. Он
обладает несколькими событиями, которые могут перехватываться приложениями,
что дает им возможность реагировать на такие системные события соответствую-
щим образом.
Основной способ использования класса FileSystemWatcher весьма прост. Сна-
чала нужно задать значения свойств, с помощью которых можно определить, где
следует осуществлять контроль, что при этом необходимо контролировать и когда
следует генерировать события, которые будут обрабатываться нашим приложением.
Затем сообщить адреса созданных обработчиков событий, с тем чтобы они могли
вызываться в момент наступления значимых событий. Наконец, следует запустить
программу и перейти в режим ожидания наступления соответствующих событий.
В таблице на стр. 575 приведены свойства, которые необходимо задать до того,
Как ПОЯВИТСЯ ВОЗМОЖНОСТЬ ИСПОЛЬЗОВать объект FileSystemWatcher.
После того как эти свойства будут заданы, необходимо создать обработчики со-
бытий ДЛЯ четырех различных событий — Changed, Created, Deleted И Renamed.
Как известно из главы 12, для этого необходимо просто создать свой собственный
Работа с файлами
Свойство
Filter
метод и присвоить его событию данного объекта. Присваивание вашего собствен-
ного обработчика событий этим методам приведет к тому, что именно ваш метод
будет вызываться при наступлении соответствующего события. Все события будут
возникать в тот момент, когда файл или директория, удовлетворяющая свойствам
Path, NotifyFiiter и Filter, будет претерпевать изменения.
Описание
P a t h Этот ПУТЬ Должен указывать на местоположение файла или директорию
подлежащие контролю.
NotifyFiiter Это свойство представляет собой некоторое сочетание значений перечислимого
типа NotifyFilters, которое позволяет определить, за наступлением каких именно
событии для данных файлов следует наблюдать. Они представляют свойства файлов
или папок, за которыми ведется наблюдение. Если какое-либо из указанных свойств
оказывается измененным, то генерируется соответствующее событие.
Данный перечислимый тип включает в себя следующие значения: Attributes
CreationTime, DirectoryName, Filename, LastAccess, LastWrite, Security, Size
иоратите внимание на то, что допускается использование различных сочетаний
этих значений посредством бинарного оператора OR.
Фильтр, определяющий, какие именно файлы подлежат контролю, например, *.txt.
После задания указанных СВОЙСТВ И событий СВОЙСТВУ EnableRaisingEvents
следует присвоить значение true, что будет означать начало наблюдения.
1. Создадим более изощренный пример, в котором будет
использоваться почти все, с чем мы познакомились
в данной главе. Создайте новый проект.
Выберите на этот раз С# Windows Application
И Назовите его FileWatch.
2. Задайте свойства различных форм в соответствии
с приведенной справа таблицей.
3. Используя приведенный ниже список, добавьте
в форму необходимые управляющие элементы
и задайте их свойства:
Свойство Значение
FormBorderStyle
MaximizeBox
MinimizeBox
Size
StartPosition
Text
FixedDialog
False
False
302, 160
CenterScreen
FileMonitor
О Textbox — Name: txtLocation; Location: 8, 24; size: 184, 20; Text: отсутствует
• Button — Name: cmdBrowse; Location: 208, 24; Size: 64, 240; Text: Browse...
• Button — Name: cmdWatch; Location: 88, 56; Size: 80, 32; Text: Watch!;
Enabled: false (мы не имеем возможности следить за файлом,
до того как он будет задан)
WalcN
• Label — Name: lblWatch; Location: 8, 104;
size: 264, 32; Text: отсутствует
• OpenFileDialog — Name: FileDialog;
Filter: All Files]*.*
В итоге ваша форма должна будет принять вид,
изображенный на рисунке слева. Серое пространство
в нижней части формы представляет собой
576 Глава 20
управляющий элемент Label, в котором будет выводиться текущее
состояние вашего приложения.
4. Для того чтобы работа выполнялась корректно, нам потребуется
добавить некоторый код. Щелкните правой кнопкой мыши
на файле Formi.cs в Solution Explorer, а затем выберите мышью
режим просмотра кода. Как всегда, нам придется добавить в проект
пространство имен system, ю для того чтобы получить доступ
к необходимым классам. Добавьте следующий код в начало
файла Formi.cs:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
w^_,,,,__^_^_^_,. using System.Data; . ..... .. .,,.,,,,,,,..., '
using System.10;
5. Теперь необходимо добавить В класс Forml Класс FileSystemWatcher.
После объявлений Объектов WinForms С модификатором private
добавьте следующий код:
private System.Windows.Forms.TextBox txtLocation;
private System.Windows.Forms.Button cmdBrowse;
private System.Windows.Forms.Button cmdWatch;
private System.Windows.Forms.Label lblWatch;
private System.Windows.Forms.OpenFileDialog FileDialog;
// Объект наблюдения за файловой системой
private FileSystemWatcher watcher;
6. Теперь Требуется ВНеСТИ Некоторый КОД В метод InitializeComponentO.
Для того чтобы получить возможность просматривать метод
InitializeComponentO, вам придется прежде всего раскрыть более
широко область, обозначенную как Windows Form Designer generated
code (код, сгенерированный программой Windows Form Designer).
Для этого щелкните мышью на маленьком окошке, в котором
нарисован знак плюс, в левой части экрана. В результате вы увидите
метод InitializeComponentO, в котором уже находится большое
количество кода, помещенного туда Visual Studio.NET.
Добавьте Следующий КОД В КОНец метода InitializeComponentO.
ЭТОТ КОД необходим ДЛЯ инициализации объекта FileSystemWatcher
и привязывает события к методам, к созданию которых
мы приступим далее:
this.watcher = new System.10.FileSystemWatcher();
this.watcher.Deleted += new System.10.FileSystemEventHandler(this.OnDelete);
this.watcher.Renamed += new System.10.RenamedEventHandler(this.OnRenamed); ч
this.watcher.Changed += new System.10.FileSystemEventHandler(this.OnChanged);;
this.watcher.Created += new System.10.FileSystemEventHandler(this.OnCreate);
V
7. Добавьте следующие четыре метода после метода
InitializeComponentO. Эти методы будут заниматься
обработкой событий, Создаваемых объектом FileSystemWatcher:
// Описание обработчиков событий.
public void OnChanged(object source, FileSystemEventArgs e)
Работа с файлами . 577
try
{
StreamWriter sw = new StreamWriter("С:/FileLogs/Log.txt",true);
sw.WriteLine("File: {0} {!}", e.FullPath, e.ChangeType.ToStringO ) ;
:••'','•••', '. • : • • . , . , • • ; • : • • • • • • : .• SW.ClOSe(); ' • ' : ' '' ' ' .'• ' '•• Л • ' : ,, • •'•• л , . : - . . : ; • • . . • , . . . . у - -
lblWatch.Text = "Wrote change event to log";
} ' •• " '
catch(IOException ex)
{ ' " • •' . .,;;>^v,';v;v:';>.-:;;;:
:\ .; . .'; :.:-
:
lblWatch.Text = "Error Writing to log*; :
public void OnRenamed(object source, RenamedEventArgs e)
try
{ ' ' ' | . :'; • ' \ . ..I ^Ш}::.Ъ:,
StreamWriter sw =new StreamWriter{"C;/FileLogs/Log.txt*,true);
sw.WriteLine("File renamed from {0} to {1}*, e.OldName, e.FullPath);
sw.Close();
lblWatch.Text = "Wrote renamed event to log";
}
catch(lOException ex)
{
lblWatch.Text = 'Error Writing to log";
public void OnDelete(object source, FileSystemEventArgs e)
{
try
{
StreamWriter sw = new StreamWriter(*C:/FileLogs/Log.txt",true);
sw.WriteLine(vF:Lle: {0} Deleted", e.FullPath);
sw.CloseO ;
lblWatch.Text = "Wrote delete event to log";
}
catch(lOException ex)
lblWatch.Text = "Error Writing to log";
public void OnCreate(object source, FileSystemEventArgs e)
{
try
{
StreamWriter sw = new StreamWriter("C:/FileLogs/Log.txt*,true);
sw.WriteLine("File: {0} Created", e.FullPath);
sw.CloseO; :
lblWatch.Text = "Wrote create event to log";
}
catch(lOException ex)
{
lblWatch.Text = "Error Writing to log";
8. Теперь нужно добавить обработчик событий для кнопки поиска
(Browse...). Проще всего этого можно добиться, позволив IDE
самостоятельно создать такой обработчик. Перейдите с помощью
мыши обратно в окно разработки формы. Нажмите мышью
578 Глава 20
на кнопке Browse... два раза. Следующий код приводит к открытию
диалога Open File, который позволяет пользователю выбрать файл,
за которым будет установлено наблюдение. Это реализуется
посредством метода showDialog {):
private void cmdBrowse_Click(object sender, System.EventArgs e)
{
if (FileDialog.ShowDialog() 1= DialogResult.Cancel )
{
txtLocation.Text = FileDialog.FileName;
}
cmdWatch.Enabled = true;
}
Метод showDialog о возвращает значение перечислимого типа
DialogResult, которое соответствует тому, каким образом пользователь
покинул диалог Open File. У пользователя имеются две возможности:
он может нажать либо кнопку ОК, либо кнопку Cancel. Необходимо
убедиться в том, что пользователь не нажимал кнопку Cancel,
поэтому, прежде чем занести выбранный пользователем файл
в управляющий элемент Textbox, мы сравниваем полученный
по завершении работы данного метода результат со значением
перечИСЛИМОГО типа DialogResult.Cancel. После ЭТОГО СВОЙСТВУ
Enabled кнопки Watch присваивается значение true — теперь
имеется возможность вести наблюдение за выбранным файлом.
9. Переходим к последнему участку кода. Выполните точно такую же
Процедуру ДЛЯ КНОПКИ Watch. Для Запуска Объекта FileSystemWatcher
добавьте следующий код:
private void cmdWatch__Click( object sender, System. Event Args e)
... {
watcher.Path =Path.GetDirectoryName(txtLocation.Text);
watcher.Filter = Path.GetFileName(txtLocation.Text);
watcher.NotifyFilter =
NotifyFilters.LastWrite I NotifyFilters.FileName I NotifyFilters.Size;
lblWatch.Text = "Watching * + txtLocation.Text;
II Начало наблюдения,
watcher.EnableRaisingEvents = true;
}
10. Необходимо убедиться в том, что директория оказывается- доступной
и в нее можно производить запись данных. Добавьте в конструктор
Formi следующий код, который будет производить проверку на
предмет существования соответствующей директории и создавать,
если она отсутствует.
public Forml()
{
//
// Необходимо для поддержки Windows Form Designer
//
InitializeComponent();
DirectoryInfo aDir = new Directorylnfo("C:/FileLogs");
if(JaDir.Exists)
aDir.CreateO ;
Работа с файлами 579
1Ж Log.t Kt -Notepad
j&ft
e : C:\TempVsf4tch\new t*Xt 0OCilH>iflt«tX$ Crested
e renamed from new t e x t «Jocumtnt.txt t o C;\TcmfW*tch\do<umeffC3..txc
F 11 # : С: Yrempwatch\new t«Xt document 11xt c r e a t ed
F i l e renamed f r « new t e x t dOGUMtftt.txt t o с;\тев>р*доch\docitnent2.txt
F i l e : C2\Ter!pwatch\clocyrnen?l.txt changed С
F i l e : с:Veupwatch\ctocumeml.xxt Changed
F i l e : C:\Teftipwatch\documertt2.txt Deleted
11. Постройте проект. Если процедура построения проекта завершится
успешно, то нажмите кнопку Browse и выберите какой-либо
текстовый файл из имеющихся на вашем компьютере.
12. Для начала наблюдения за файлом нажмите кнопку Watch.
Единственное видимое изменение, которое произойдет с вашим
приложением,— это появление управляющего элемента с надписью,
указывающей, за каким именно файлом ведется наблюдение.
13. С помощью Windows Explorer
перейдите к тому самому файлу,
за которым установлено наблюдение.
Откройте этот файл в Notepad,
добавьте в него произвольный Ч
текст. Сохраните файл.
14. Теперь можно просмотреть
регистрационный файл, в котором
будут отражены все изменения.
Откройте файл C:\FileLogs\Log.txt
в Notepad. Вы должны увидеть
описание произошедших с ним
изменений (см. рис. слева).
Как это работает —
Наблюдение за состоянием файловой системы
Это очень простое приложение, однако оно позволяет продемонстрировать, как
работает объект FiieSystemwatcher. Если вы зададите для данной директории *.*,
то отслеживаться будут все изменения, происходящие в данной директории.
Большая чаСТЬ КОДа В Приложении Касается НаСТрОЙКИ Объекта FiieSystemwatcher,
для того чтобы можно было вести наблюдение в нужном месте:
watcher.Path =Path.GetDirectoryName(txtLocation.Text);
watcher.Filter = Path.GetFileName(txtLocation.Text);
watcher.NotifyFilter =
NotifyFilters.LastWrite I NotifyFilters.FileName I NotifyFilters.Size;
lblWatch.Text = 'Watching * + txtLocation.Text;
// Начало наблюдения,
watcher.EnableRaisingEvents = true;
В этом коде сначала задается путь к директории, в которой будет вестись на-
блюдение, для чего используется новый для нас объект, с которым нам еще не
приходилось сталкиваться,— объект system, io.Path. Это статический класс,
очень напоминающий статический объект File. Он обладает большим количеством
методов, позволяющих выполнять манипуляции и извлекать информацию из строк,
представляющих ведущие к файлам пути. Сначала мы используем этот объект для
получения имени директории, введенной пользователем в текстовом окне, посред-
ством метода GetDirectoryName ().
В следующей строке задается фильтр, который будет использоваться объектом.
В качестве фильтра может фигурировать просто имя файла, в этом случае наблю-
дение будет вестись только за указанным файлом, а может использоваться какая-
либо строка вроде *.txt — в таком случае наблюдение будет вестись за всеми
файлами с расширением .txt, находящимися в данной директории. Здесь снова ис-
пользуется статический объект Path для извлечения информации из местоположе-
ния файла, заданного пользователем.
580 Глава 20
Свойство NotifyFiiter представляет собой комбинацию из нескольких пере-
числимых значений типа NotifyFiiters, с помощью которых определяется, что
входит в понятие изменения. В данном примере мы требуем, что наше приложение
должно уведомляться об изменениях времени последней записи в файл, имени
файла или размера файла. После внесения изменений в пользовательский интер-
фейс МЫ присваиваем СВОЙСТВУ EnableRaisingEvents значение true, ЧТО ПРИВОДИТ
к началу ведения наблюдения.
Однако перед этим нам приходится создать объект и определить обработчики
событий:
this.watcher = new System. 10.FileSystemWatcher() ;
this.watcher.Deleted += new System.10.FileSystemEventHandler(this.OnDelete);
this.watcher.Renamed += new System.10.RenamedEventHandler(this.OnRenamed);
this.watcher.Changed += new System.10.FileSystemEventHandler(this.OnChanged);
this.watcher.Created += new System.10.FileSystemEventHandler(this.OnCreate);
Именно таким образом нам удается привязать обработчики событий, отправля-
емых ведущим наблюдение объектом, к созданным нами частным методам. Именно
в этих методах мы принимаем решение о том, каким образом следует обрабаты-
вать наступившее событие. Не забудьте, что уведомление приходит после наступ-
ления события.
В методах обработчиков событий, которые используются в настоящем примере,
просто производится соответствующая запись в файл регистрации. Реакция на на-
ступившее событие может быть гораздо сложнее — это зависит от самого прило-
жения. Например, если в директорию добавляется новый файл, то его можно
перенести куда-либо в другое место или, прочитав его содержимое, запустить
какой-либо новый процесс, в котором будет использоваться содержащаяся в нем
информация. Наши возможности безграничны!
Асинхронный доступ н файлам
Доступ ко всем файлам на протяжении настоящей главы осуществлялся син-
хронным образом. Это означает, что выполнение приложения будет приостановле-
но до тех пор, пока операция чтения или записи не будет завершена. Это
оказывается вполне приемлемым для большинства приложений, однако иногда
возникает необходимость записать очень большое количество данных, при этом
у приложения совершенно отсутствует необходимость дожидаться окончания опе-
рации записи. Или, например, требуется считать информацию из файла, находя-
щегося в сети с медленным соединением; в этом случае ваше приложение могло
бы продолжать выполнять какую-либо другую работу, параллельно внося соответ-
ствующие изменения в управляющие элементы пользовательского интерфейса, от-
ражающие процесс загрузки данных. Такой способ доступа к данным называется
асинхронным. Обычно это означает, что приложение может выполнять какие-либо
другие действия параллельно с неким процессом, например, с операцией ввода/
вывода файла, вместо того чтобы дожидаться окончания этого процесса.
Класс Filestream предоставляет несколько методов, предназначенных для осу-
ществления асинхронного доступа к файлам. Это несколько более сложный способ
получения доступа к файлам, однако он обладает тем преимуществом, что вы по-
лучаете возможность выполнять какие-либо другие действия в то время, пока про-
исходит считывание или запись файла.
Процесс считывания файла начинается с вызова метода BeginReadO. Этому
методу передаются параметры аналогичные тем, которые передаются основному
Работа с файлами 581
метолу Reado, плюс дополнительные параметры, необходимые для осуществления
асинхронного процесса.
IAsyncResult BeginRead(byte[] array, int offset, int numByte, AsyncCallack
userCallback, object stateObject);
Первые три параметра абсолютно идентичны параметрам метода Reado. Пара-
метр userCallback — это специально создаваемый метод, с помощью которого
.NET Framework возвращает приложению сообщение о том, что процедура чтения
завершена. Этот параметр будет рассматриваться позднее. Поскольку этот пара-
метр не является обязательным, то вместо него можно передавать null, что мы
и сделаем в нашем первом примере. Последний параметр — это задаваемый поль-
зователем объект состояния, который используется совместно с методом, возвра-
щающим сообщение, для разделения нескольких асинхронных операций. Поскольку
существует возможность использовать один и тот же метод сразу для нескольких
операций, то можно использовать данный параметр для передачи какой-либо стро-
ки или данных, позволяющих идентифицировать данную асинхронную операцию.
Поскольку метод для возвращения сообщения нами не используется, вместо этого
параметра также передается null.
Возвращаемый объект IAsyncResult является абстрактным представлением
процесса чтения. В нем содержится большое количество свойств и методов, кото-
рые позволяют получать информацию о состоянии процесса, а также определять,
что данный процесс закончился.
Для завершения процесса чтения вызывается метод EndReado; ему передается
Объект IAsyncResult, который был ВОЗВращен методом BeginReadO. ПоЗНаКОМИМ-
ся с тем, как все это работает, с помощью примера.
Практикум.- асинхронное считывание файлов
1. Создайте новый проект. Выберите пункт меню С# Console Application
И назовите его AsyncRead.
2. Добавьте следующие строки в начало файла ciassi.cs:
using System;
using System.10;
using System.Text;
3. Добавьте следующий код в метод Maino:
static void Main(string[] args)
{ . ...... . . ............ . ................ ... ,...,...,,.......,...,..,.....,..,., ,.....,..,... -
byte[] byData = new byte[100];
char[] charData = new Char[100];
try
FileStream aFile = new FileStream("../../Classl,cs ",FileMode.Open);
aFile.Seek(0,-SeekOrigin.Begin) ;
//Начало процедуры асинхронного чтения из файла •
System.IAsyncResult asResult = aFile.BeginRead(byData,0,100,null/null);
//•Выполнение других действий параллельно с чтением;данных ; '
while (]asResult/IsGompleted)
Console.WriteLine(//Reading from file...");
582 Глава 20
aFile.EndRead(asResult);
Decoder d - Encoding.ASCII.GetDecoder();
d.GetChars(byData,0,byData.Length,charData,0);
Console.WriteLine(charData);
Console.ReadLine();
return;
}
catch(lOException e)
{
Console,WriteLine("An 10 exception has been thrown!'
Console,WriteLine(e.ToString());
Console.ReadLine();
•• • •••. r e t u r n ; . ••:• • : • . •••.• •. • ••• • • ' • : : •'••> : •:.•.•:•••: •• ••• ••••• • • • • ••••
iron f xle.
frcir* f ile»
from file,
& д i
Beading IVora file»
Bea<$i«g from:file»
Heading frow f i l e .
Beauing- frora file»
Ita&elifn^ Гж*сич f i l e .
B d i ffr or» ffiille»
floors file*
fi*orj file.
from file*
g j y j
usiny System.I0s
i S t l
nanespace
4. Запустите приложение — вы сможете
увидеть, что начало файла ciassi.cs
будет записано в файл после
неСКОЛЬКИХ Строк "Reading from
file...*, как показано на рисунке
слева.
Как это работает —
Асинхронное считывание файлов
В данном примере происходит достаточно
много интересного. Прежде всего мы запус-
каем процедуру считывания файла с помощью
следующей строки:
System.IAsyncResult asResult = aFile.BeginRead(byData/0/100/null/null);
Это приводит к тому, что приложению возвращается объект IAsyncResult,
с помощью которого можно запрашивать информацию о том, завершилась ли на
данный момент процедура считывания или нет. Пока процедура не будет завершена,
можно выполнять какие-либо другие действия на фоне выполняющейся процедуры
считывания файла:
while (J asResult.IsCompleted)
Console.WriteLine("Reading from filel");
}
В этом примере не выполняется никаких действий, кроме простого вывода на
консоль сообщения о том, что программа находится в состоянии ожидания, однако
приложение может выполнять параллельно какие-нибудь гораздо более сложные
действия. Однако наши возможности по-прежнему сильно ограничены, поскольку
нам приходится постоянно крутиться в цикле while, ожидая завершения выполне-
ния метода Read(). К счастью, существует другой способ — как раз здесь в дело
вступают Остальные параметры метода BeginRead.
Асинхронный доступ к файлам
с использованием событий
Другой способ осуществления доступа к файлам в асинхронном режиме вклю-
чает использование метода, возвращающего сообщение, который позволяет .NET
Framework предать приложению информацию о том, что операция завершена.
Работа с файлами 583
И хотя приложение в этот момент может заниматься чем-либо другим, оно немед-
ленно уведомляется о завершении операции чтения.
Для этого необходимо создать метод, которому будет передаваться объект
iAsyncResuit. Этот метод может являться составной частью как текущего класса,
так и какого-либо другого. В настоящем примере мы включили его как член само-
го класса, однако это не является обязательным требованием.
практикум: асинхронное считывание файлов с использованием событий
1. Создайте новый проект. Выберите пункт меню С# Console Application
И назовите его AsyncReadEvents.
2. Измените ИМЯ класса С Classl на AsyncRead.
Программа должна выглядеть следующим образом:
using System;
namespace AsyncReadEvents
/// <summary>
/// Краткое описание класса Classl.
/// </summary>
class AsyncRead
static void Main(string[] args)
// Что сделать: добавить код для запуска приложения
3. Включите следующие строки кода в начало файла ciassi.cs:
using System;
using System.10;
using System.Text;
4. В этом примере мы поступим несколько по-другому. Добавьте
следующие переменные в класс AsynchRead:
public class AsynchRead
byte[] byData;
: ; char[] charData;
5. ВкЛЮЧИТе Следующий КОД КОНСТруКТОра Класса AsynchRead
непосредственно вслед за только что определенными переменными:
public AsynchRead()
byData = new byte[100] ;
charData = new Char[100];
try
• • С - - ' ,:-
FileStream aFile = new FileStream ("../.. /Classl. cs* , FileMode. Open);
System.AsyncCallbackcb = new AsyncCallback(this.KandleRead);
System.IAsyncResuit aResult = aFile.BeginRead(byData,0,100, cb,"Read Classl.cs"
584 Глава 20
catch(IOException e)
{
Console.WriteLine(• An 10 excepti-on has been thrown! •);
Console.WriteLine(e.ToStringO);
Console.ReadLineO ;
• • • • • • r e t u r n ; • . • •••. • •.. •. •••••• /. • • , • •• . • : .. • : ,
6. Теперь добавим метод, возвращающий сообщение,— HandieReadO,
который был зарегистрирован нами перед этим в методе BeginReadO.
Добавьте этот код в произвольное место класса AsynchRead.
private void HandleRead(IAsyncResult ar)
Decoder d = Encoding.UTF8.GetDecoder();
d.GetChars(byData, 0, byData.Length, charData, 0) ;
Console.WriteLine("Value of s t a t e object for t h i s operation: {0}",
ar.AsyncState);
Console.WriteLine(charData);
7. В заключение добавьте приведенный ниже код в метод MainO.
В нем Создается НОВЫЙ Экземпляр Объекта AsynchRead,
что позволяет запустить приложение,
s t a t i c void Main(string[] args)
AsynchRead aClass = new AsynchRead();
for(int x=0;x<200;x++) -
Console.WriteLine(x);
Console.ReadLine()
return; :
8. Запустите приложение.
Вы увидите выходной поток,
подобный представленному
на рисунке слева.
Как это работает —
Асинхронное считывание файлов
с использованием событий
Этот пример обладает фундаментальными
отличиями от предшествующего. В нем метод
Main о создает экземпляр объекта ciassi,
а затем продолжает выполнять свою собст-
венную работу — вывод порядковых чисел
на консоль; весь смысл этого заключается
в том, что теперь этому методу не приходится отслеживать процедуру считывания,
и он может выполнять какие-либо другие действия, совершенно от этой процедуры
не зависящие.
Считывание файла в асинхронном режиме запускается в конструкторе класса
ciassi, при этом в системе регистрируется метод, возвращающий сообщение.
Работа с файлами 585
Следующие после открытия объекта Filestream две строки кода выполняют все
для этого необходимое:
System.AsyncCallback cb = new AsyncCallback(this.HandleRead);
System.IAsyncResult aResult = aFile.BeginRead(byData,O,100,0b,"Read Classl.cs");
В первой строке происходит создание объекта AsyncCallback, который переда-
ется в качестве четвертого параметра методу BeginRead (). Для этого создается со-
вершенно новый объект AsyncCallback, передавая адрес метода, который будет
принимать объект IAsyncResult в качестве своего единственного параметра.
В следующей строке осуществляется вызов метода BeginReado, которому переда-
ются стандартные данные, с которыми мы познакомились ранее, и, кроме того,
объект AsyncCallback и строка "Read ciassi.cs". Это — задаваемый пользовате-
лем объект состояния, который будет использоваться нами позднее — в методе,
возвращающем сообщение. Это не имеет никакого смысла для данного сценария,
поскольку мы осуществляем только один запрос на асинхронное считывание, но
если бы таких запросов было несколько, то нам потребовался бы способ отличать
один от другого.
В методе HandleReadO не происходит ничего такого, чего бы нам не встреча-
лось ранее. Он просто перекодирует данные и выводит символьный массив на кон-
соль. В нем также ВЫВОДИТСЯ Значение СВОЙСТВа AsyncState объекта IAsyncResult.
private void HandleRead(IAsyncResult ar)
{
Decoder d = Encoding.UTF8.GetDecoder();
. d.GetChars(byData, 0,-by-Data.Length, charData, 0) ;
Console.WriteLine("Value of s t a t e object for t h i s operation: {0}*,
ar.AsyncState);
Console.WriteLine(charData);
>
Наиболее интересен тот факт, что данный метод не вызывается приложением.
Он вызывается системой .NET Framework в тот момент, когда завершается проце-
дура считывания файла. Это позволяет приложению продолжать обработку какой-
либо иной информации, пока выполняется относительно медленная процедура счи-
тывания файла.
Асинхронная запись файлов
До сих пор мы рассматривали только чтение файлов в асинхронном режиме,
однако все эти способы вполне применимы и при записи в файл в асинхронном ре-
жиме. В этом случае также имеется возможность выбора — использовать или не
использовать события, при этом преимущества обоих способов остаются теми же.
Поскольку мы уже неоднократно сталкивались с процедурой записи файлов,
а принципы доступа к файлам в асинхронном режиме оказываются идентичными,
в конце данной главы дается упражнение на асинхронную запись файлов.
Итоги
Из настоящей главы мы узнали, что такое потоки и почему они используются
в .NET Framework для осуществления доступа к файлам и другим последователь-
ным устройствам. Мы рассмотрели основные классы, находящиеся в пространстве
имен System. IO: File, Filelnfo И FileStream, а также обсудили вопрос, ДЛЯ чего
ОНИ МОГут ИСПОЛЬЗОВатЬСЯ. Мы также изучили классы StreamReader И StreamWriter
586 Глава 20
и то, насколько они оказываются полезными при осуществлении записи в поток
и чтении из потока. Мы узнали, каким образом может осуществляться чтение и за-
пись в файлы произвольного доступа посредством класса Filestream. Наконец, мы
рассмотрели более сложные решения, которые можно строить с использованием
.NET Framework. Мы построили приложение, которое позволяет вести наблюде-
ние За файлами И директориями С ПОМОЩЬЮ класса FileSystemWatcher.
В результате нами было рассмотрено:
• Открытие файлов
• Чтение из файлов
• Запись в файлы
• Различия Между классами StreamWriter И StreamReader,
С ОДНОЙ СТОрОНЫ, И КЛаССОМ F i l e S t r e a m , С другой.
• Преимущества и недостатки асинхронного доступа к файлам
• Наблюдение за файловой системой
С использованием класса FileSystemWatcher
Упражнения
1. Как называется пространство имен, которое должно импортироваться
для того, чтобы приложение могло работать с файлами?
2. В каких случаях для записи в файл следует использовать
объект FileStream вместо объекта StreamWriter?
3. Какие методы класса StreamWriter позволяют производить
считывание данных из файлов, и что конкретно делает
каждый из них?
4. Какие события может генерировать класс FileSystemWatcher,
и для чего они предназначены?
5. Модифицируйте приложение FileWatch, созданное нами
в настоящей главе. Предусмотрите в нем возможность включать
и отключать процедуру наблюдения без необходимости выходить
из приложения.
6. Создайте приложение, которое производит запись данных в файл
в асинхронном режиме. Создайте произвольным образом
большой массив данных и запишите его в файл.


Категория: информатика | Просмотров: 661 | Добавил: basic | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Календарь
«  Февраль 2010  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

krutoto.ucoz.ru
Бесплатный конструктор сайтов - uCoz