Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП ЛР №6.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
248.83 Кб
Скачать

Асинхронный доступ к файлам

Приложение может выполнять какие-то действия параллельно с процессом ввода/вывода файла, вместо ожидания окончания этого процесса. Процесс считываня файла начинается с вызова метода BeginRead(), методу передаются параметры аналогичные методу Read() + дополнительные, необходимые для осуществления асинхронного процесса.

byte[] byteData = new byte[100];

char[] charData = new char[100];

try

{

FileStream fs = new FileStream("d:\\log.txt", FileMode.Open);

fs.Seek(0, SeekOrigin.Begin); // на начало файла

// начало процедуры асинхронного чтения из файла, первые 3 параметра аналогичные Read()

// 4й пар.-делегат на метод, к.будет вызван по завершению чтения

// 5й пар.-заданный пользов. объект состояния, предназначенный для передачи некой

// строки или данных, позволяющих идентифицир. данную асинхронную операцию

IAsyncResult asResult = fs.BeginRead(byteData, 0, byteData.Length, null, null);

// выполнение друхиг действий паралельно с чтение данных

while (!asResult.IsCompleted) // хранит инф. о сотоянии процесса

{

// другие действия только здесь...

MessageBox.Show("reading from file...");

}

// завершение чтения. передается объект IAsyncResult, возвращенный методом Begin()

fs.EndRead(asResult);

// обработка данных, без нее завершить процесс безсмысленно

Decoder d = Encoding.ASCII.GetDecoder();

d.GetChars(byteData, 0, byteData.Length, charData, 0);

MessageBox.Show(new string(charData));

fs.Close();

}

catch (Exception err)

{

MessageBox.Show(err.Message);

}

Другой, более совершенный, способ осуществления доступа к файлам в асинхронном режиме включает использование метода, возвращающего сообщение (о том что операция завершена).

public class AsyncRead

{

byte[] byteData;

char[] charData;

public AsyncRead()

{

byteData = new byte[1000];

charData = new char[1000];

try

{

FileStream fs = new FileStream("d:\\log.txt", FileMode.Open);

fs.Seek(0, SeekOrigin.Begin); // на начало файла

// делегат указатель на функцию, которая будет обрабатываться

AsyncCallback cb = new AsyncCallback(this.HandleRead);

IAsyncResult aResult = fs.BeginRead(byteData, 0, byteData.Length, cb, "read log.txt");

}

catch (IOException err) { MessageBox.Show(err.Message); }

}

// действия которые будут выполняться по завершению обработки

public void HandleRead(IAsyncResult ar)

{

Decoder d = Encoding.ASCII.GetDecoder();

d.GetChars(byteData, 0, byteData.Length, charData, 0);

MessageBox.Show(new string(charData));

}

private void button2_Click(object sender, EventArgs e)

{

AsyncRead ar = new AsyncRead();

// продолжаем основные действия

for (int i = 0; i < 50; i++) { MessageBox.Show(i.ToString()); }

}

Создается экземпляр класса AsyncReader, а заме продолжается выполнение – вывод порядковых чисел на консоль; теперь этому методу не приходиться отслеживать процедуру считывания, и он может выполнять какие-либо другие действия, совершенно от этой процедуры не зависящие. Метод HandleRead вызывается системой, когда завершается процедура считывания файла. Это позволяет приложению продолжать обработку какой-либо иной информации, пока выполняется относительно медленная процедура считывания файла.

Пример:

namespace WindowsApplication1

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

this.btnOK.Enabled = false;

this.LoadOccupation();

this.txtName.Tag = false;

this.txtAge.Tag = false;

this.txtAddress.Tag = false;

this.txtName.Validating += new CancelEventHandler(this.txtBoxEmpty_Validating);

this.txtAddress.Validating += new CancelEventHandler(this.txtBoxEmpty_Validating);

this.txtAge.Validating += new CancelEventHandler(this.txtBoxEmpty_Validating);

this.txtAge.KeyPress += new KeyPressEventHandler(txtAge_KeyPress);

this.txtName.TextChanged += new EventHandler(txtBox_TextChanged);

this.txtAddress.TextChanged += new EventHandler(txtBox_TextChanged);

this.txtAge.TextChanged += new EventHandler(txtBox_TextChanged);

}

private void btnOK_Click(object sender, EventArgs e)

{

string output;

output = "Имя: " + this.txtName.Text + "\r\n";

output += "Адресс: " + this.txtAddress.Text + "\r\n";

output += "Профессия: " + this.cmbOccupation.Text + "\r\n";

output += "Пол: " + (string)(this.rdoMale.Checked ? "Мужской" : "Женский") + "\r\n";

output += "Возраст: " + this.txtAge.Text;

this.txtOutput.Text = output;

}

// чтение из файла

private void LoadOccupation()

{

try

{

// создание объекта StreamReader

System.IO.StreamReader sr = new System.IO.StreamReader("occupation.txt");

string input;

do

{

input = sr.ReadLine(); // построчное чтение

if (input != "") // пропуск пустых строк

this.cmbOccupation.Items.Add(input);

} while (sr.Peek() != -1); // -1 возвращается когда достигнут конец потока

sr.Close();

}

catch (Exception)

{

MessageBox.Show("Файл не найден");

}

}

// запись в файл

private void SaveOccupation()

{

try

{

System.IO.StreamWriter sw = new System.IO.StreamWriter("occupation.txt");

foreach (string item in this.cmbOccupation.Items)

{

sw.WriteLine(item); // запись

}

sw.Flush(); // очистка буфера

sw.Close();

}

catch (Exception)

{

MessageBox.Show("Файл не найден");

}

}

private void ValidateAll()

{

this.btnOK.Enabled = ((bool)(this.txtName.Tag) &&

(bool)(this.txtAddress.Tag) &&

(bool)(this.txtAge.Tag));

}

private void cmbOccupation_KeyDown(object sender, KeyEventArgs e)

{

// если Text отсутствует в семействе Items то добавляем его

int index = 0;

ComboBox cb = (ComboBox)sender;

if (e.KeyCode == Keys.Enter)

{

// осуществ. поиск строки и не является чувствительным к регистру

index = cb.FindStringExact(cb.Text);

if (index < 0)

cb.Items.Add(cb.Text);

else

cb.SelectedIndex = index;

// указывает на то что событие KeyDown нами обработано

e.Handled = true;

}

}

}

}

protected override void Dispose(bool disposing)

{

// сохранение элементов

SaveOccupation();

if (disposing && (components != null))

{

components.Dispose();

}

base.Dispose(disposing);

}