Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Клас Thread




Підтримка багатопоточності здійснюється в.NET в основному за допомогою простору імен System.Threading. Деякі типи цього простору описані в таблиці 10.1

 

 

Таблиця 10.1.

Деякі типи простору імен System.Threading

 

Тип Опис
Interlocked Клас, що забезпечує синхронізований доступ до змінних, які використовуються в різних потоках
Monitor Клас, що забезпечує синхронізацію доступу до об'єктів
Mutex Клас-примітив синхронізації, який використовується також для синхронізації між процесами
ReaderWriterLock Клас, що визначає блокування, що підтримує один доступ на запис і декілька, - на читання
Thread Клас, який створює потік, встановлює його пріоритет, отримує інформацію про стан
ThreadPool Клас, використовуваний для управління набором взаємозв'язаних потоків, - пулом потоків
Timer Клас, що визначає механізм виклику заданого методу в задані інтервали часу для пулу потоків

 

Продовження таблиці 10.1

 

Тип Опис
WaitHandle Клас, що інкапсулює об'єкти синхронізації, які чекають доступу до ресурсів, що розділяються
IOCompletionCallback Клас, одержуючий зведення про операцію введення-виведення, що завершилася
ThreadStart Делегат, що представляє метод, який має бути виконаний при запуску потоку
TimerCallback Делегат, що представляє метод, оброблювальний виклики від класу Timer
WaitCanback Делегат, що представляє метод для елементів класу Threadpool
ThreadPriority Перелічення, що описує пріоритет потоку
ThreadState Перелічення, що описує стан потоку

 

Первинний потік створюється автоматично. Для запуску вторинних потоків використовується клас Thread. При створенні об'єкту-потоку йому передається делегат, що визначає метод, виконання якого виділяється в окремий потік:

 

Thread t = new Thread (new ThreadStart(ім'я_методу));

 

Після створення потоку заданий метод починає в ньому свою роботу, а первинний потік продовжує виконуватися. У лістингу 10.10 приведений приклад одночасної роботи двох потоків.

 

Лістинг 10.10. Створення вторинного потоку

using System;

using System.Threading;

namespace ConsoleApplication1

{

class Program

{

static public void Hedgehog() // метод для вторинного потоку

{

for (int i = 0; i < 6; ++i)

{

Console.WriteLine(i);

Thread.Sleep(1000);

}

}

static void Main()

{

Console.WriteLine("Первинний потік " +

Thread.CurrentThread.GetHashCode());

Thread ta = new Thread(new ThreadStart(Hedgehog));

Console.WriteLine("Вторинний потік " + ta.GetHashCode());

ta.Start();

for (int i = 0; i > -6; --i)

{

Console.Write(" " + i);

Thread.Sleep(400);

}

}

}

}

Результат роботи програми:

Первинний потік 1

Вторинний потік 3

-1 -21

-3 -42

-53

 

У лістингу використовується метод Sleep, що зупиняє функціонування потоку на задану кількість мілісекунд. Як бачите, обидва потоки працюють одночасно. Якби вони працювали з одним і тим же файлом, він був би зіпсований так само, як і приведене виведення на консоль, тому такий спосіб розпаралелювання обчислень має сенс тільки для роботи з різними ресурсами.

У таблиці 10.2 перераховані основні елементи класу Thread.

 

Таблиця 10.2.

Основні елементи класу Thread

 

Елемент Вигляд Опис
CurrentThread Статична властивість Повертає посилання на потік, що виконується (тільки для читання)
IsAlive Властивість Повертає true або false залежно від того, запущений потік чи ні
IsBackground Властивість Повертає або встановлює значення, яке показує, чи є цей потік фоновим
Name Властивість Установка текстового імені потоку
Priority Властивість Отримати/встановити пріоритет потоку (використовуються значення перелічення ThreadPrority)
ThreadState Властивість Повертає стан потоку (використовуються значення перелічення ThreadState)
Abort Метод Генерує виключення ThreadAbortException. Виклик цього методу зазвичай завершує роботу потоку
GetData, SetData Статичні методи Повертає (встановлює) значення для вказаного слота в поточному потоці

Продовження таблиці 10.2

 

Елемент Вигляд Опис
GetDomain, GetDomainID Статичні методи Повертає посилання на домен додатку (ідентифікатор домена додатку), в рамках якого працює потік
GetHashCode Метод Повертає хеш-код для потоку
Sleep Статичний метод Припиняє виконання поточного потоку на задану кількість мілісекунд
Interrupt Метод Перериває роботу поточного потоку
Join Метод Блокує викликаючий потік до завершення іншого потоку або вказаного проміжку часу і завершує потік
Resume Метод Відновлює роботу після припинення потоку
Start Метод Починає виконання потоку, визначеного делегатом ThreadStart
Suspend Метод Припиняє виконання потоку. Якщо виконання потоку вже припинене, то ігнорується

 

Можна створити декілька потоків, які спільно використовуватимуть один і той же код. Приклад приведений в лістингу 10.11.

 

Лістинг 10.11. Потоки, що використовують один об'єкт

using System;

using System.Threading;

 

namespace ConsoleApplication1

{

class Classl

{

public void Do()

{

for (int i = 0; i < 4; ++i)

{

Console.Write(" " + i); Thread.Sleep(3);

}

}

}

class Program

{

static void Main()

{

Classl a = new Classl();

Thread tl = new Thread(new ThreadStart(a.Do));

tl.Name = "Second";

Console.WriteLine("Потік " + tl.Name);

tl.Start();

Thread t2 = new Thread(new ThreadStart(a.Do));

t2.Name = "Third";

Console.WriteLine("Потік " + t2.Name);

t2.Start();

}

}

}

 

Результат роботи програми:

Потік Second

Потік Third

0 0 1 1 2 2 3 3

 

Варіанти виведення можуть декілька розрізнятися, оскільки один потік перериває виконання іншого в невідомі моменти часу.

Для того, щоб блок коду міг використовуватися в кожен момент тільки одним потоком, застосовується оператор lock. Формат оператора:

 

lock (вираз) блок_операторів

 

Вираз визначає об'єкт, який потрібно заблокувати. Для звичайних методів як вираз використовується ключове слово this. Для статичних - typeof (клас). Блок операторів задає критичну секцію коду, яку потрібно заблокувати.

Наприклад, блокування операторів в приведеному раніше методі Do виглядає таким чином:

 

public void Do()

{

Lock(this)

{

for (int i = 0; i < 4; ++i)

{

Console.Write(" " + i);

Thread.Sleep(30);

}

}

}

Результат роботи програми:

Потік Second

Потік Third

0 1 2 3 0 1 2 3

 

 

10.3.2. Асинхронні делегати

Делегат можна викликати на виконання або синхронно, як у всіх приведених раніше прикладах, або асинхронний за допомогою методів BeginInvoke і EndInvoke. При виклику делегата за допомогою методу BeginInvoke середовище виконання створює для виконання методу окремий потік і повертає управління операторові, наступному за викликом. При цьому в початковому потоці можна продовжувати обчислення

Якщо при виклику BeginInvoke був вказаний метод зворотного виклику, цей метод викликається після завершення потоку. Метод зворотного виклику також задається за допомогою делегата, при цьому використовується стандартний делегат AsyncCallback. У методі, зворотного виклику для набуття повертаємого значення і вихідних параметрів застосовується метод EndInvoke.

Якщо метод зворотного виклику не був вказаний в параметрах методу BeginInvoke, метод EndInvoke можна використовувати в потоці, що ініціював запит. У лістингу 10.11 наводяться два приклади асинхронного виклику методу, що виконує розкладання числа на множники.

Клас Factorizer містить метод Factorize, що виконує розкладання на множники. Цей метод асинхронно викликається двома способами: у методі Num1 метод зворотного виклику задається в BeginInvoke, в методі Num2 мають місце очікування завершення потоку і безпосередній виклик EndInvoke.

 

Лістинг 10.11. Асинхронні делегати

using System;

using System.Threading;

using System.Runtime.Remoting.Messaging;

 

namespace AsynchroneDelegat

{

// асинхронний делегат

public delegate bool AsyncDelegate(int Num, out int m1, out int m2);

 

// клас, що виконує розкладання числа на множники

public class Factorizer

{

public bool Factorize(int Num, out int m1, out int m2)

{

m1 = 1; m2 = Num;

for (int i = 2; i < Num; i++)

if (0 == (Num % 1)) { m1 = i; m2 = Num / i; break; }

if (1 == m1) return false;

else return true;

}

}

// клас, одержуючий делегати і результати

public class PNum

{

private int Number;

public PNum(int number)

{

Number = number;

}

 

[OneWayAttribute()]

// метод, одержуючий результати

public void Res(IAsyncResult ar)

{

int m1, m2;

// отримання делегата з IAsyncResult

AsyncDelegate ad = (AsyncDelegate)((AsyncResult)ar).AsyncDelegate;

// отримання результатів виконання методу Factorize

ad.EndInvoke(out m1, out m2, ar);

// виведення результатів

Console.WriteLine("Перший спосіб: множетелі {0}: {1} {2}", Number, m1, m2);

}

 

}

// демонстраційний клас

public class Simple

{

// спосіб 1: використовується функція зворотного виклику

public void Num1()

{

Factorizer f = new Factorizer();

AsyncDelegate ad = new AsyncDelegate(f.Factorize);

int Num = 1000589023, tmp;

// створення екземпляра класу, який буде викликаний

// після завершення роботи методу Factorize

PNum n = new PNum(Num);

// завдання делегата методу зворотного виклику

AsyncCallback callback = new AsyncCallback(n.Res);

// асинхронний виклик методу Factorize

IAsyncResult ar = ad.BeginInvoke(Num, out tmp, out tmp, callback, null);

// тут виконання якихось подальших дій

}

// спосіб 2: використовується очікування закінчення виконання

public void Num2()

{

Factorizer f = new Factorizer();

AsyncDelegate ad = new AsyncDelegate(f.Factorize);

 

int Num = 1000589023, tmp;

 

// створення екземпляра класу, який буде викликаний

// після завершення роботи методу Factorize

PNum n = new PNum(Num);

// завдання делегата методу зворотного виклику

AsyncCallback callback = new AsyncCallback(n.Res);

// асинхронний виклик методу Factorize

IAsyncResult ar = ad.BeginInvoke(Num, out tmp, out tmp, null, null);

// очікування завершення

ar.AsyncWaitHandle.WaitOne(10000, false);

if (ar.IsCompleted)

{

int m1, m2;

// отримання результатів виконання методу Fractorize

ad.EndInvoke(out m1, out m2, ar);

// виведення результатів

Console.WriteLine("Другий спосіб: множетелі {0}: {1} {2}", Num, m1, m2);

}

}

}

class Program

{

static void Main()

{

Simple s = new Simple();

s.Num1();

s.Num2();

}

 

}

}

 

Результат роботи програми:

Перший спосіб: множники 1000589023: 7 142941289

Другий спосіб: множники 1000589023: 7 142941289

 

Атрибут [ OneWayAttribute() ] позначає метод якщо не має повертаємого значення і вихідних параметрів.

 

10.4. Рекомендації по програмуванню

 

Делегати широко застосовуються в бібліотеці.NET як самостійно, так і для підтримки механізму подій.

Делегат є особливим видом класу, що нагадує собою інтерфейс, але, на відміну від нього, задає тільки одну сигнатуру методу. У мові C ++ аналогом делегата є вказівка на функцію, але вона не володіє безпекою і зручністю використання делегата. Завдяки делегатам стає можливою гнучка організація взаємодії, що дозволяє підтримувати узгоджений стан взаємозв'язаних об'єктів.

Основною метою створення багатопотокових застосувань є підвищення загальної продуктивності програми. Проте розробка багатопотокових застосувань складніша, оскільки при цьому виникають проблеми синхронізації даних, пов'язаних з можливістю доступу до одних і тих же даних з боку декількох потоків.

РОЗДІЛ 11. РОБОТА З ФАЙЛАМИ

 

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

Введення-виведення в С# виконується за допомогою підсистеми введення-виведення і класів бібліотеки. NET. У цьому розділі розглядається обмін даними з файлами і консоллю. Обмін даними реалізується за допомогою потоків.

Потік (stream) - це абстрактне поняття, що відноситься до будь-якого перенесення даних від джерела до приймача. Потоки забезпечують надійну роботу як із стандартними, так і з визначеними користувачем типами даних. Потік визначається як послідовність байтів і не залежить від конкретного пристрою, з яким проводиться обмін (оперативна пам'ять, файл на диску, клавіатура або принтер).

Обмін з потоком для підвищення швидкості передачі даних проводиться, як правило, через спеціальну область оперативної пам'яті - буфер. Буфер виділяється для кожного відкритого файлу. При записі у файл вся інформація спочатку прямує в буфер і там накопичується до тих пір, поки весь буфер не заповниться. Тільки після цього або після спеціальної команди скидання відбувається передача даних на зовнішній пристрій. При читанні з файлу дані спочатку прочитуються в буфер, причому не стільки, скільки запрошується, а скільки поміщається в буфер.

Механізм буферізації дозволяє швидше і ефективно обмінюватися інформацією із зовнішніми пристроями.

Для підтримки потоків бібліотека. NET містить ієрархію класів, основна частина якої представлена на рис. 11.1. Ці класи визначені в просторі імен System.IO. Окрім класів там описана велика кількість перелічень для завдання різних властивостей і режимів.

Класи бібліотеки дозволяють працювати в різних режимах з файлами, каталогами і областями оперативної пам'яті. Короткий опис класів приведений в таблиці 11.1.

Як можна бачити з таблиці, виконувати обмін із зовнішніми пристроями можна на рівні:

- двійкового представлення даних (BinaryReader, BinaryWriter);

- байтів (FileStream);

- тексту, тобто символів (StreamWriter, StreamReader).

У. NET використовується кодування Unicode, в якому кожен символ кодується двома байтами. Класи, що працюють з текстом, є оболонками класів, що використовують байти, і автоматично виконують те, що кодується з байтів в символи і назад.

 

 

 

Рис. 11.1. Класи бібліотеки. NET для роботи з потоками

 

Двійкові і байтові потоки зберігають дані в тому ж вигляді, в якому вони представлені в оперативній пам'яті, тобто при обміні з файлом відбувається побітове копіювання інформації. Двійкові файли застосовуються не для перегляду їх людиною, а для використання в програмах.

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

Прямий доступ у поєднанні з відсутністю перетворень забезпечує високу швидкість отримання потрібної інформації.

Методи форматованого введення, за допомогою яких можна виконувати введення з клавіатури або з текстового файлу значень арифметичних типів, в С# не підтримуються. Для перетворення з символьного в числове представлення використовуються методи класу Convert або метод Parse, розглянуті в попередніх розділах.

 

Таблиця 11.1

 

Основні класи простору імен System.IO

 

Клас Опис
BinaryReader, BinaryWriter Читання і запис значень простих вбудованих типів (цілочисельних, логічних, рядкових і т. п.) у внутрішній формі уявлення
BufferedStream Тимчасове зберігання потоку байтів (наприклад, для подальшого перенесення в постійне сховище)
Directory, Directorylnfo, File, Filelnfo Робота з каталогами або фізичними файлами: створення, видалення, придбання властивостей. Можливості класів File і Directory реалізовані в основному у вигляді статичних методів. Аналогічні класи DirectoryInfo і FileInfo використовують звичайні методи
FileStream Довільний (прямий) доступ до файлу, представленого як потік байтів
MemoryStream Довільний доступ до потоку байтів в оперативній пам'яті
StreamWriter, StreamReader Читання з файлу і запис у файл текстової інформації (довільний доступ не підтримується)
StringWriter, StringReader Робота з текстовою інформацією в оперативній пам'яті

 

Форматоване виведення, тобто перетворення з внутрішньої форми представлення числа в символьну, зрозумілу людині, виконується за допомогою перевантажених методів ToString.

Окрім перерахованих класів в бібліотеці.NET є класи XmlTextReader і XmlTextWriter, призначені для формування і читання коду у форматі XML.

Розглянемо прості способи роботи з файловими потоками. Використання класів файлових потоків в програмі припускає наступні операції:

1. Створення потоку і зв’язування його з фізичним файлом.

2. Обмін (уведення-виведення).

3. Закриття файлу.

Кожен клас файлових потоків містить декілька варіантів конструкторів, за допомогою яких можна створювати об'єкти цих класів різними способами і в різних режимах.

Наприклад, файли можна відкривати тільки для читання, тільки для запису або для читання і запису. Ці режими доступу до файлу містяться в переліченні FileAccess, визначеному в просторі імен System. IO. Константи перелічення приведені в таблиці 11.2.

 

 

Таблиця 11.2

Значення FileAccess

 

Значення Опис
Read Відкрити файл тільки для читання
ReadWrite Відкрити файл для читання і запису
Write Відкрити файл тільки для запису

 

Можливі режими відкриття файлу визначені в переліченні FileMоdе (таблиця. 11.3).

 

Таблиця 11.3

Значення FilеМоdе

 

Значення Опис
Append Відкрити файл, якщо він існує, і встановити поточний покажчик в кінець файлу. Якщо файл не існує, створити новий файл
Create Створити новий файл. Якщо в каталозі вже існує файл з таким же ім'ям, він буде стертий
CreateNew Створити новий файл. Якщо в каталозі вже існує файл з таким же ім'ям, виникає виключення IOEхсерtion
Open Відкрити існуючий файл
OpenOrCreate Відкрити файл, якщо він існує. Якщо немає, створити файл з таким ім'ям
Truncate Відкрити існуючий файл. Після відкриття вміст файлу видаляється

 

Режим FileMode.Append можна використовувати тільки спільно з доступом типу FileAccess.Write, тобто для файлів, що відкриваються для запису.

Режими сумісного використання файлу різними користувачами визначає перелічення FileShare (таблиця 11.4).

Таблиця 11.4

Значення FileShare

 

Значення Опис
None Сумісне використання відкритого файлу заборонене. Запит на відкриття даного файлу завершується повідомленням про помилку
Read Дозволяє відкривати файл для читання одночасно декільком користувачам. Якщо цей прапор не встановлений, запити на відкриття файлу для читання завершуються повідомленням про помилку
ReadWrite Дозволяє відкривати файл для читання і запису одночасно декільком користувачам
Write Дозволяє відкривати файл для запису одночасно декільком користувачам

11.1. Потоки байтів

 

Уведення-виведення у файл на рівні байтів виконується за допомогою класу FileStream, який є спадкоємцем абстрактного класу Stream, що визначає набір стандартних операцій з потоками. Елементи класу Stream описані в таблиці 11.5.

 

Таблиця 11.5

Елементи класу Stream

 

Елемент Опис
BeginRead, BeginWrite Почати асинхронне введення або виведення
CanRead, CanSeek, CanWrite Властивості, що визначають, які операції підтримує потік: читання, прямий доступ і/або запис
Сlose Закрити поточний потік і звільнити пов'язані з ним ресурси (сокети, покажчики на файли і т. п.)
EndRead, EndWrite Чекати завершення асинхронного введення; закінчити асинхронне виведення
Flush Записати дані з буфера в пов'язане з потоком джерело даних і очистити буфер. Якщо для даного потоку буфер не використовується, то цей метод нічого не робить
Length Повернути довжину потоку в байтах
Position Повернути поточну позицію в потоці
Read, ReadByte Підрахувати послідовність байтів (або один байт) з поточного потоку і перемістити покажчик в потоці на кількість лічених байтів
Seek Встановити поточний покажчик потоку на задану позицію
SetLength Встановити довжину поточного потоку
Write, WriteByte Записати послідовність байтів (або один байт) в поточний потік і перемістити покажчик в потоці на кількість записаних байтів

 

Клас FileStream реалізує ці елементи для роботи з дисковими файлами. Для визначення режимів роботи з файлом використовуються стандартні перелічення FileMode, FileAccess і FileShare. Значення цих перелічень приведені в таблицях 11.2-11.4. У лістингу 11.1 представлений приклад роботи з файлом. У прикладі демонструються читання і запис одного байта і масиву байтів, а також позиціонування в потоці.

 

 

Лістинг 11.1. Приклад використання потоку байтів

using System;

using System.IO;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace examp74

{

class Class1

{

static void Main()

{

FileStream f = new FileStream("test.txt",

FileMode.Create, FileAccess.ReadWrite);

f.WriteByte(100); // у початок файлу записується число 100

byte[] х = new byte[10];

for (byte i = 0; i < 10; ++i)

{

х[i] = (byte)(10 - i);

f.WriteByte(i); // записується 10 чисел від 0 до 9

}

f.Write(х, 0, 5); // записується 5 елементів масиву

byte[] у = new byte[20];

f.Seek(0, SeekOrigin.Begin); // поточний покажчик - на початок

f.Read(у, 0, 20); // читання з файлу в масив

foreach (byte elem in у) Console.Write(" " + elem);

Console.WriteLine();

f.Seek(5, SeekOrigin.Begin); // поточний покажчик - на 5-й елемент

int а = f.ReadByte(); // читання 5-го елементу

Console.WriteLine(а);

а = f.ReadByte(); // читання 6-го елементу

Console.WriteLine(а);

Console.WriteLine(" Поточна позиція в потоці " + f.Position);

f.Close();

}

}

}

 

Результат роботи програми:

100 01234 56789 10 98760000

Поточна позиція в потоці 7

Поточна позиція в потоці спочатку встановлюється на початок файлу (для будь-якого режиму відкриття, окрім Append) і зрушується на одну позицію при записі кожного байта.

Для установки бажаної позиції читання використовується метод Seek, що має два параметри: перший задає зсув в байтах щодо точки відліку, що задається другим. Точки відліку задаються константами перелічення SeekOrigin: початок файлу - Begin, поточна позиція - Current і кінець файлу - End.

У даному прикладі файл створювався в поточному каталозі. Можна вказати і повний шлях до файлу, наприклад:

 

FileStream f = new FileStream(@"D:\C#\test.txt",

FileMode.Create, FileAccess.ReadWrite);

 

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

У разі непередбачених ситуацій середовище виконання генерує різні виключення, обробку яких слід передбачити в програмі, наприклад:

· FileNotFoundException, якщо файлу у вказаному каталозі не існує;

· DirectoryNotFoundException, якщо не існує вказаний каталог;

· ArgumentException, якщо невірно заданий режим відкриття файлу;

· IOException, якщо файл не відкривається із-за помилок введення-виведення.

Можливі і інші виняткові ситуації.

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

 

try

{

FileStream f = new FileStream(@"d:\C#\test.tx", FileMode.Open, FileAccess.Read);

// дії з файлом

f.Close();

}

catch(FileNotFoundException e)

{

Console.WriteLine(е.Message);

Console.WriteLine(" Перевірте правильність імені файлу!"); return;

}

catch(Exception e)

{

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

}

При закритті файлу звільняються всі пов'язані з ним ресурси, наприклад, для файлу, відкритого для запису, у файл вивантажується вміст буфера. Тому рекомендується завжди закривати файли після закінчення роботи, особливо файли, відкриті для запису. Якщо буфер потрібно вивантажити, не закриваючи файл, використовується метод Flush.




Поделиться с друзьями:


Дата добавления: 2014-12-27; Просмотров: 1102; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.193 сек.