Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
16
Добавлен:
27.03.2016
Размер:
77.82 Кб
Скачать

Пріоритети потоків

Властивість Priority визначає, скільки часу на виконання буде виділено потокові щодо інших потоків того ж процесу. Існує 5 градацій пріоритету потоку:

enum ThreadPriority { Lowest, BelowNormal, Normal, AboveNormal, Highest }

Значення пріоритету стає істотним, коли одночасно виповнюються кілька потоків.

Установка пріоритету потоку на максимум ще не означає роботу в реальному часі (real-time), тому що існують ще пріоритет процесу додатка. Щоб працювати в реальному часі, потрібно використовувати клас Process із простору імен System.Diagnostics для підняття пріоритету процесу (якщо що, я вам цього не говорив):

Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;

Від ProcessPriorityClass.High один крок до найвищого пріоритету процесу – Realtime. Установлюючи пріоритет процесу в Realtime, ви говорите операційній системі, що хочете, щоб ваш процес ніколи не витіснявся. Якщо ваша програма випадково потрапить у нескінченний цикл, операційна система може бути цілком заблокована. Врятувати вас у цьому випадку зможе тільки кнопка вимикання харчування. З цієї причини ProcessPriorityClass.High вважається максимальним пріоритетом процесу, придатним до вживання.

Якщо real-time додаток має користувальницький інтерфейс, може бути не бажано піднімати пріоритет його процесу, тому що відновлення екрана буде з'їдати надто багато часу CPU – гальмуючи весь комп'ютер, особливо якщо UI досить складний. (Хоча, коли я це пишу, програма інтернет-телефонії Skype не дає такого ефекту, може бути, тому, що її інтерфейс досить простий.) Зменшення пріоритету головного потоку в сполученні з підвищенням пріоритету процесу гарантує, що real-time потік не буде витіснятися перемальовуванням екрана, але не рятує від гальм весь комп'ютер, тому що операційна система усе ще буде виділяти багато часу CPU усьому процесові у цілому. Ідеальне рішення полягає в тому, щоб тримати роботу в реальному часі і користувальницький інтерфейс у різних процесах (з різними пріоритетами), що підтримують зв'язок через Remoting або shared memory. Поділювана пам'ять вимагає звертання до Win32 API (погуглите про CreateFileMapping і MapViewOfFile).

Обробка виключень

Обрамлення коду створення і запуску потоку блоками try/catch/finally має мало змісту. Подивитеся наступний приклад:

public static void Main()

{

try

{

new Thread(Go).Start();

}

catch(Exception ex)

{

// Сюди ми ніколи не потрапимо!

Console.WriteLine("Виключення!");

}

static void Go() { throw null; }

}

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

public static void Main()

{

new Thread(Go).Start();

}

static void Go()

{

try

{

...

throw null; // це виключення буде піймано нижче

...

}

catch(Exception ex)

{

Логирование виключення і/або сигнал іншим потокам

...

}

}

Починаючи с.NET 2.0, неопрацьоване виключення в будь-якому потоці приводить до закриття всього додатка, а значить ігнорування виключень – це не наш метод. Отже, блок try/catch необхідний у кожнім методі потоку – принаймні, у додатках не для власного вживання – щоб уникнути закриття додатка через неопрацьоване виключення. Це може бути досить обтяжливо, особливо для програмістів Windows Forms, що використовують глобальний перехоплювач виключень, як показано нижче:

using System;

using System.Threading;

using System.Windows.Forms;

static class Program

{

static void Main()

{

Application.ThreadException += HandleError;

Application.Run(new MainForm());

}

static void HandleError(object sender, ThreadExceptionEventArgs e)

{

Логирование виключення, завершення або продовження роботи

}

}

Подія Application.ThreadException виникає, коли виключення генерується в коді, що був викликаний (можливо, по ланцюжку) з оброблювача повідомлення Windows (наприклад, від клавіатури, миші і т.д.) – коротше кажучи, практично з будь-якого коду додатка Windows Forms. Оскільки це чудово працює, з'являється почуття помилкової безпеки, - що усі виключення будуть оброблені цим центральним оброблювачем. Виключення, що виникають у робочих потоках – гарний приклад виключень, що не ловляться в Application.ThreadException (код у методі Main – інший такий приклад, включаючи конструктор MainForm, що відпрацьовує до запуску циклу обробки повідомлень).

.NET Framework надає низкоуровневое подія для глобальної обробки виключень - AppDomain.UnhandledException. Ця подія відбувається, коли є неопрацьоване виключення в будь-якому потоці і для будь-яких типів додатків (з користувальницьким інтерфейсом або без нього). Однак, хоча це і гарний спосіб реєстрації неопрацьованих виключень, він не надає ніякого способу запобігти закриттю додатка або придушити повідомлення .NET про неопрацьоване виключення.

Соседние файлы в папке Semestr2