Використання потоків в Visual C # (Sharp)

На компютерах під управлінням операційної системи Windows завдання можуть виконуватися двома способами: за допомогою потоків і за допомогою процесів Процесявляє собою виконання програми, для якої операціоая система виділяє ресурси, що включають, між інших, і кванти часу А потік – Це легкий процес, виконуваний в контексті головного процесу

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

ПРИМІТКА

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

Потік можна створити таким чином, що він буде виконуватися незалежно від соавшего його потоку У наступному прикладі головний потік створює два дочірні потоку, кожен з яких виводить текст у вікно консолі Зверніть увагу на те, що тип Thread та інші споріднені типи, використовувані в прикладах цієї Гли, знаходяться У просторі імен SystemThreading, тобто в код необхідно добити сходинку using SystemThreading

Thread threadl = new Thread(

delegate() { ConsoleWriteLine(&quothello there&quot) }) Thread thread2 = new Thread(

() =&gt { ConsoleWriteLinef&quotWell then goodbye&quot) })

threadl Start () ,- thread2Start()

Потік породжується створенням екземпляра типу Thread з наступним викликом методу start О Клас Thread містить всю функціональність, необхідну для запуску та управління багатозадачності

При запуску потоку, типу Thread потрібно код для виконання Для цього примяти делегат Threadstart, який передається класу Thread через конструктор У даному прикладі тип Threadstart не використовується, т к в обох потоках примяти програмні конструктиви, які не потребують оголошення делегата У першому потоці (threadl) використовується анонімний метод, а в другому (thread2) – лямбдираженіе Виклик методу start () Запускає виконання потоком функціональнті анонімного методу або лямбда-вирази

Результатом виконання прикладу потоків може бути наступний висновок:

Well then goodbye hello there

Я кажу можливо, тому ЩО hello виводити перед goodbye Такий висновок означає, що другий потік (thread2) почав виконуватися перед першим потоком (threadl) Але послідовність виведення вітання і прощання може також бути і в логічному порядку, що демонструє природу потоків – паралель і причину, чому програмування потоків є таким важким

Уявіть на секунду, що приклад коду потоків виконувався не паралельно, а послідовно У такому випадку метод threadl star t про завжди викликався би першим, а метод thread2start () – Другий, в результаті чого ми б завжди здовалісь перед прощанням Послідовне виконання не представляє для людей ніяких проблем з розумінням Але уявити в розумі взаємодія нколькіх завдань одночасно – набагато складніше завдання У той час як виконання паралельних потоків не є проблемою для компютерів, ярку цього виконання програмують люди, більш звичні до послідовного мислення, і тому створювана ними паралельна логіка може виявитися Сержао помилки

Розробку добре налагодженого потокового програми можна порівняти з попи зібрати в одному місці кілька котів чи собак Якщо не дотримуватися належну обережність з потоками і їх синхронізацією, тоді це буде подібно спробі загнати в один кут десять кішок, що майже неможливо, т к кішки не реагують добре на команди Але якщо бути обережним і прикласти належне старанність, ТДА це буде походити на збір в одному кутку десяти собак – завдання досить легка, якщо собаки видресирувані

Виклик методу star t про запускає потік, таким чином, починаючи виконання зади Код, що викликав потік, не очікує завершення виконання створеного ним поки, тому що цей потік є повністю незалежним від нього Тому при хвилюванні пакетного процесу, потрібно буде чекати, поки не завершаться всі потоки Запуск на виконання декількох потоків здійснюється за допомогою Викликає логіки Зухвала логіка потрібно тільки для запуску процесів, тому для її роботи потрібно дуже короткий час, порівняно з часом для іолненія потоків Але якщо завершити виконання викликає потоку, то також буде примусово завершено виконання всіх його дочірніх потоків, в резулате чого можливе спотворення даних

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

Thread thread = new Thread(

delegated { ConsoleWriteLinef&quothello there&quot) ThreadSleep(2000) })

threadStart()

threadJoin()

Виклик методу Join про в останній сходинці коду блокує викликає потік до тих пір, поки не завершиться виконання викликаного ним потоку Метод Thread, sleep про переводить потік в стан сну на вказане в параметрі час, в даному прикладі на 2000 мілісекунд або 2 секунди

Таким чином, проблема передчасного завершення викликає потоку вирішена, але яку користь приносить очікування викликає потоком завершення створеного потоку У даному прикладі використання методу Join () Не приносить ніякої користі тут просто демонструвалося його застосування Але якщо визающій потік виконує декілька потоків, то перш ніж продовжити своє іолненіе, він повинен дочекатися завершення всіх цих потоків Тому в Сіту з кількома виконуються потоками слід викликати метод Join про абсолютно для всіх цих потоків

Варіантом методу join про є вказівка ​​тайм-ауту в параметрі Припустимо, що для виконання обробки запущеному потоку в гіршому випадку потрібно щонайбільше 5 хвилин Тоді, якщо протягом 5 хвилин потік не завершить виконання самостійно, то ми завершуємо його примусово Далі наводиться соответс код:

if (threadJoin(300000)) { threadAbort()

}

У прикладі виклик методу Joint) змушує виконуваний потік очікувати протягом 300000 мілісекунд (5 хвилин), перш ніж продовжити виконання У разі тайм-ауту повертається значення false, і виконання потоку примусово зершается допомогою методу Abort ()

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*