Многонишково програмиране и синхронизация

186

Upload: kumiko

Post on 14-Jan-2016

98 views

Category:

Documents


1 download

DESCRIPTION

Програмиране за .NET Framework. http:// www.nakov.com / dotnet-project /. Многонишково програмиране и синхронизация. Михаил Стойнов Софтуерен инженер , Sciant Inc. www.sciant.com Microsoft Student Consultant www.fmi.uni-sofia.bg/microsoft/. Необходими знания. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Многонишково програмиране и синхронизация
Page 2: Многонишково програмиране и синхронизация

Многонишково Многонишково програмиране и програмиране и синхронизациясинхронизация

Програмиране заПрограмиране за .NET Framework .NET Frameworkhttp://http://www.nakov.comwww.nakov.com//dotnet-projectdotnet-project//

Михаил СтойновМихаил СтойновСофтуерен инженер, SciantСофтуерен инженер, Sciant Inc.Inc. www.sciant.com

Microsoft Student ConsultantMicrosoft Student Consultantwww.fmi.uni-sofia.bg/microsoft/

Page 3: Многонишково програмиране и синхронизация

Необходими знанияНеобходими знания Базови познания за Базови познания за .NET Framework .NET Framework и и CLRCLR Базови познания за общата система от Базови познания за общата система от

типове в типове в .NET (Common Type System).NET (Common Type System) Базови познания за езика Базови познания за езика C#C# Базови познания по операционни системиБазови познания по операционни системи АтрибутиАтрибути

Page 4: Многонишково програмиране и синхронизация

СъдържаниеСъдържание МногозадачностМногозадачност НишкиНишки СинхронизацияСинхронизация Асинхронни извикванияАсинхронни извиквания

Забележка: Под някои Забележка: Под някои слайдовеслайдове в полето забележки има в полето забележки има подробно описание на съдържанието на подробно описание на съдържанието на слайдаслайда

Page 5: Многонишково програмиране и синхронизация

Многозадачност – съдържаниеМногозадачност – съдържание МногозадачностМногозадачност

Проблемът – защо многозадачност?Проблемът – защо многозадачност? Ползите от многозадачносттаПолзите от многозадачността Решението – процеси и нишкиРешението – процеси и нишки Прилики и разликиПрилики и разлики Какво предлагат?Какво предлагат? Кога са удобни нишките?Кога са удобни нишките? Многозадачност – видовеМногозадачност – видове Имплементации на многозадачностИмплементации на многозадачност Application DomainsApplication Domains

НишкиНишки СинхронизацияСинхронизация Асинхронни извикванияАсинхронни извиквания

Page 6: Многонишково програмиране и синхронизация

ПроблемътПроблемът Има случаи, в които вашето Има случаи, в които вашето

приложение трябва да изпълни приложение трябва да изпълни времеотнемащи операции или да времеотнемащи операции или да чака за освобождаването на ресурсчака за освобождаването на ресурс

Има случаи, в които вашето Има случаи, в които вашето приложение трябва да извършва приложение трябва да извършва операция на заден планоперация на заден план

Нужен е механизъм, който да Нужен е механизъм, който да позволява няколко операции да се позволява няколко операции да се извършват едновременноизвършват едновременно

Page 7: Многонишково програмиране и синхронизация

Ползите от многозадачносттаПолзите от многозадачността

Performance – на машината с няколко Performance – на машината с няколко процесора работи по-бързопроцесора работи по-бързо

ResponsivenessResponsiveness – системата отговаря – системата отговаря максимално бързо при интерактивна максимално бързо при интерактивна работаработа

ThroughputThroughput – подобряване на – подобряване на производителността производителността Пример със супермаркета – обслужване Пример със супермаркета – обслужване

на няколко каси едновременнона няколко каси едновременно

Обслужване на много потребители Обслужване на много потребители едновременноедновременно

Page 8: Многонишково програмиране и синхронизация

Демонстрация Демонстрация ##11 Защо е нужна многозадачностЗащо е нужна многозадачност

Page 9: Многонишково програмиране и синхронизация

Решението –Решението – процеси и нишкипроцеси и нишки Процесът представлява съвкупността Процесът представлява съвкупността

от памет, стек и кода на приложениетоот памет, стек и кода на приложението OSOS използват използват процесипроцеси ((process)process), за да , за да

разграничават различните приложенияразграничават различните приложения НишкатаНишката ((threadthread) ) е основната единица, е основната единица,

на която на която OSOS може да заделя може да заделя процесорно времепроцесорно време

В един процес различните задачи се В един процес различните задачи се изпълняват от отделни нишкиизпълняват от отделни нишки

В един процес има поне една нишкаВ един процес има поне една нишка

Page 10: Многонишково програмиране и синхронизация

Процес Процес vs.vs. Нишка Нишка ПриликиПрилики

собствен стек (собствен стек (stack)stack) приоритетприоритет exception handlersexception handlers

РазликиРазлики Процесите са изолирани един от друг по Процесите са изолирани един от друг по

отношение на памет и данниотношение на памет и данни Нишките в един процес споделят Нишките в един процес споделят

паметтапаметта ( (променливите и даннитепроменливите и данните)) на на този процестози процес

Процесите съдържат изпълнимия код, а Процесите съдържат изпълнимия код, а нишките го изпълняватнишките го изпълняват

Page 11: Многонишково програмиране и синхронизация

Какво предлагат нишките?Какво предлагат нишките? Използването на няколко нишки Използването на няколко нишки

Създава впечатление за извършване на Създава впечатление за извършване на няколко задачи едновременноняколко задачи едновременно

ПричинатаПричината:: Времето, през което една Времето, през което една нишка държи процесора е много кратконишка държи процесора е много кратко

НапримерНапример Потребителят може да въвежда данни в Потребителят може да въвежда данни в

текстообработваща програматекстообработваща програма докато се докато се печатат данни на принтерпечатат данни на принтер

Би било недопустимо ако потребителят Би било недопустимо ако потребителят трябваше да изчака принтерът да трябваше да изчака принтерът да свърши работата сисвърши работата си

Page 12: Многонишково програмиране и синхронизация

Кога са удобни нишките?Кога са удобни нишките? Случаи, в които е удобно да се Случаи, в които е удобно да се

използват нишки:използват нишки: Обслужване на много потребители Обслужване на много потребители

едновременно, например едновременно, например WebWeb сървър сървър Комуникация през мрежаКомуникация през мрежа (sockets) (sockets) Извършване на времеотнемаща Извършване на времеотнемаща

операцияоперация Различаване на задачите по приоритетРазличаване на задачите по приоритет За да може потребителският интерфейс За да може потребителският интерфейс

да продължи да “откликва” на да продължи да “откликва” на потребителски заявки, докато на заден потребителски заявки, докато на заден план се извършва друга задачаплан се извършва друга задача

Page 13: Многонишково програмиране и синхронизация

Многозадачност – Многозадачност – Изпреварваща и кооперативнаИзпреварваща и кооперативна

Кооперативна многозадачност Кооперативна многозадачност (cooperative multitasking)(cooperative multitasking) Нишката сНишката сама решава колко процесорно ама решава колко процесорно

време време йй е необходимо е необходимо Сваля Сваля се се от процесора само ако е от процесора само ако е

свършила свършила или или чака за някакъв ресурсчака за някакъв ресурс Изпреварваща многозадачност Изпреварваща многозадачност

((preemptive multitasking)preemptive multitasking) Планировчикът (Планировчикът (task scheduler) task scheduler) заделя заделя

предварително някакво процесорно времепредварително някакво процесорно време Без значение дали е приключила, нишката Без значение дали е приключила, нишката

се снема от процесорасе снема от процесора

Page 14: Многонишково програмиране и синхронизация

Многозадачност – Многозадачност – Изпреварваща и кооперативнаИзпреварваща и кооперативна

При кооперативната многозадачност:При кооперативната многозадачност: Една нишка може дълго време да държи Една нишка може дълго време да държи

процесорапроцесора Заради нея останалите нишки могат да Заради нея останалите нишки могат да

чакат недопустимо дългочакат недопустимо дълго

Някои системи използват Някои системи използват комбиниран варианткомбиниран вариант Нишки с висок приоритет се държат Нишки с висок приоритет се държат

кооперативно спрямо нишките с по-кооперативно спрямо нишките с по-нисък приоритетнисък приоритет

Page 15: Многонишково програмиране и синхронизация

Имплементации на многозадачностИмплементации на многозадачност

ApartmentApartment

Global DataGlobal Data

InstructionInstruction

InstructionInstruction

ThreadThread

ApartmentApartment

Global DataGlobal Data

InstructionInstruction

InstructionInstruction

ThreadThread

InstructionInstruction

InstructionInstruction

ThreadThread

InstructionInstruction

InstructionInstruction

ThreadThread

ProcessProcess

Global DataGlobal Data

Apartment ThreadingApartment Threading Free ThreadingFree Threading

Page 16: Многонишково програмиране и синхронизация

Application DomainApplication Domain .NET Framework добавя още едно ниво на .NET Framework добавя още едно ниво на

абстракция между нишка и процес – абстракция между нишка и процес – Application DomainApplication Domain

AppDomain-ът дава логическа изолацияAppDomain-ът дава логическа изолация При процесите изолацията е физическа, тъй При процесите изолацията е физическа, тъй

като е имплементиран на ниво OSкато е имплементиран на ниво OS

ПредимстваПредимства Подобрена производителностПодобрена производителност Ниво на изолация –Ниво на изолация – като при процесакато при процеса Връзка м/у нишки без proxyВръзка м/у нишки без proxy Извършва type checkingИзвършва type checking

System.AppDomainSystem.AppDomain

Page 17: Многонишково програмиране и синхронизация

System.AppDomainSystem.AppDomain

AppDomain #1AppDomain #1

Global DataGlobal Data

InstructionInstruction

ThreadThread

AppDomain #2AppDomain #2

InstructionInstruction

ThreadThread

InstructionInstruction

ThreadThreadAppDomain #4AppDomain #4

Global DataGlobal Data

AppDomain #3AppDomain #3

Global DataGlobal Data

InstructionInstruction

ThreadThread

Page 18: Многонишково програмиране и синхронизация

Нишки – съдържаниеНишки – съдържание МногозадачностМногозадачност НишкиНишки

Как работят нишкитеКак работят нишките Живот на нишкитеЖивот на нишките По-важни членовеПо-важни членове ПриоритетПриоритет СъстоянияСъстояния ThreadThread LocalLocal StorageStorage Thread-Relative Static FieldsThread-Relative Static Fields ПрекратяванеПрекратяване НеудобстваНеудобства Повреждане на данниПовреждане на данни

СинхронизацияСинхронизация Асинхронни извикванияАсинхронни извиквания

Page 19: Многонишково програмиране и синхронизация

Как работи многонишковосттаКак работи многонишковостта

InstructionInstruction

InstructionInstruction

InstructionInstruction

InstructionInstruction

InterruptInterrupt

Tim

e S

lice

Tim

e S

lice

ThreadThread

ThreadThread

ThreadThread

ThreadThread

ThreadThread

Ru

nn

ing

Qu

eue

Ru

nn

ing

Qu

eue

Return to QueueReturn to Queue

Pull From QueuePull From Queue

Page 20: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask1));oTask1)); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 21: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask1));oTask1)); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 22: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask1)oTask1));); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 23: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(new ThreadStart(ft.ft.DDoTask1oTask1)));); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 24: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(new ThreadStart(ft.ft.DDoTask1oTask1));)); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 25: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask1));oTask1)); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 26: Многонишково програмиране и синхронизация

Малък примерМалък примерclass FirstThread {class FirstThread { public void public void DDoTask1() {oTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void public void DDoTask2() {oTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starter {class Starter { static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask1));oTask1)); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.new ThreadStart(ft.DDoTask2));oTask2)); t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 27: Многонишково програмиране и синхронизация

Малък примерМалък пример//Резултат://Резултат:Thread1:job(1)Thread1:job(1)Thread1:job(2)Thread1:job(2)Thread2:job(1)Thread2:job(1)Thread1:job(3)Thread1:job(3)............Thread1:job(53)Thread1:job(53)Thread2:job(46)Thread2:job(46)Thread2:job(47)Thread2:job(47)Thread1:job(54)Thread1:job(54)............Thread1:job(97)Thread1:job(97)Thread2:job(99)Thread2:job(99)Thread1:job(98)Thread1:job(98)Thread1:job(99)Thread1:job(99)

Page 28: Многонишково програмиране и синхронизация

Демонстрация #Демонстрация #22 Нишки – малък примерНишки – малък пример

Page 29: Многонишково програмиране и синхронизация

Жизнен цикъл на нишкитеЖизнен цикъл на нишкитеStart()Start()

IsAlive

Suspend()Suspend() Sleep()Sleep() WaitX()WaitX() Join()Join()

ThreadThreadStoppedStopped

Suspended WaitSleepJoin WaitSleepJoin WaitSleepJoin Stopped

Interrupt()Interrupt() AimedAimedThreadThread

DestroyedDestroyed

Interrupt()Interrupt()

Resume()Resume()

All Done

Abort()Abort()

Expire timeExpire time NotifiedNotified

Page 30: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart );public Thread( ThreadStart );

Създава инстанцияСъздава инстанция Подава се делегат с метод, който да се Подава се делегат с метод, който да се

изпълни при стартиранеизпълни при стартиране Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 31: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start);

Sleep()Sleep() ““Приспива” текущата нишка за указания Приспива” текущата нишка за указания

брой милисекунди (и наносекунди)брой милисекунди (и наносекунди) Извиква се само от самата нишкаИзвиква се само от самата нишка

Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 32: Многонишково програмиране и синхронизация

Малко повече за Малко повече за Sleep()Sleep()

InstructionInstruction

InstructionInstruction

InstructionInstruction

InstructionInstruction

Sleep()Sleep()

Sle

ep Q

ueu

eS

leep

Qu

eue

ThreadThread

ThreadThread

ThreadThread

ThreadThread

ThreadThread

Ru

nn

ing

Qu

eue

Ru

nn

ing

Qu

eue

Clock InterruptClock Interruptfr

om

Qu

eue

fro

m Q

ueu

e

TT

TT

TT

TT

TT

To

Sle

ep Q

ueu

eT

o S

leep

Qu

eue

Page 33: Многонишково програмиране и синхронизация

Приспиване на нишкаПриспиване на нишкаusing System;using System;using System.Threading;using System.Threading;public class ThreadSleeppublic class ThreadSleep{{ public static Thread worker;public static Thread worker; public static Thread worker2;public static Thread worker2; public static void Main()public static void Main() {{ Console.WriteLine("Entering void Main!");Console.WriteLine("Entering void Main!"); worker = new Thread(newworker = new Thread(new ThreadStart(Counter));ThreadStart(Counter)); worker2 = new Thread(newworker2 = new Thread(new ThreadStart(Counter2));ThreadStart(Counter2)); worker.Start();worker.Start(); worker2.Start();worker2.Start(); Console.WriteLine("Exiting void Main!");Console.WriteLine("Exiting void Main!"); }} (примерът продължава)(примерът продължава)

Page 34: Многонишково програмиране и синхронизация

Приспиване на нишкаПриспиване на нишка public static void Counter()public static void Counter() {{ Console.WriteLine("Entering Counter");Console.WriteLine("Entering Counter"); for(int i = 1; i < 50; i++)for(int i = 1; i < 50; i++) {{ Console.Write(i + " ");Console.Write(i + " "); if(i == 10)if(i == 10) Thread.Sleep(1000);Thread.Sleep(1000); }} Console.WriteLine("Console.WriteLine("\n\nExiting Counter");Exiting Counter"); }} public static void Counter2()public static void Counter2() {{ Console.WriteLine("Entering Counter2");Console.WriteLine("Entering Counter2"); for(int i = 51; i < 100; i++)for(int i = 51; i < 100; i++) {{ Console.Write(i + " "); Console.Write(i + " "); if( i == 70 )if( i == 70 ) Thread.Sleep(5000);Thread.Sleep(5000); }} Console.WriteLine(“Console.WriteLine(“\n\nExiting Counter2");Exiting Counter2"); }}}}

Page 35: Многонишково програмиране и синхронизация

Демонстрация #Демонстрация #33 Използване на Използване на Thread.Sleep()Thread.Sleep()

Page 36: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep()

Suspend()Suspend() Ако нишката е в състояние Ако нишката е в състояние RunningRunning, я , я

преустановява временно (suspend)преустановява временно (suspend) ако е преустановена, не се случва нищоако е преустановена, не се случва нищо

Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 37: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend()

Resume()Resume() Подновява нишка, която е била Подновява нишка, която е била

преустановена (suspended)преустановена (suspended) Ако нишката работи, не прави нищоАко нишката работи, не прави нищо

IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 38: Многонишково програмиране и синхронизация

Демонстрация #Демонстрация #44 Използване на Използване на SuspendSuspend()() и и ResumeResume()()

Page 39: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume()

IsAliveIsAlive truetrue, ако е стартирана и не е спряна , ако е стартирана и не е спряна

прекъсната или прекратенапрекъсната или прекратена Повече информация дава Повече информация дава ThreadStateThreadState

IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 40: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive

IsBackgroundIsBackground Преден план (foreground) и фонов Преден план (foreground) и фонов

режим (background)режим (background) Свойство за смяна/извличанеСвойство за смяна/извличане

IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 41: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground

IsThreadPoolThreadIsThreadPoolThread Свойство за смяна/извличанеСвойство за смяна/извличане truetrue, ако нишката принадлежи на , ако нишката принадлежи на

managed thread pool, иначе managed thread pool, иначе falsefalse NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 42: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread

NameName Всяка нишка в Всяка нишка в .NET Framework.NET Framework може да може да

има имеима име Свойство за смяна/извличанеСвойство за смяна/извличане на иметона името

PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 43: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName

PriorityPriority LowestLowest, , BelowNormalBelowNormal, , NormalNormal (по (по

подразбиране), подразбиране), AboveNormalAboveNormal, , HighestHighest Свойство за промяна/извличанеСвойство за промяна/извличане

ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 44: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority

ThreadStateThreadState Съдържа състоянието на нишката – Съдържа състоянието на нишката –

зависи от това дали нишката работизависи от това дали нишката работи Свойство само за извличанеСвойство само за извличане

Abort()Abort() Interrupt()Interrupt() Join()Join() Start()Start()

Page 45: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState

Abort()Abort() Обикновено “убива” нишкатаОбикновено “убива” нишката Хвърля Хвърля ThreadAbortExceptionThreadAbortException в в

извиканата нишкаизвиканата нишка Interrupt()Interrupt() Join()Join() Start()Start()

Page 46: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort()

Interrupt()Interrupt() Събужда нишка ако е в състояние Събужда нишка ако е в състояние

WaitSleepJoinWaitSleepJoin, иначе не прави нищо, иначе не прави нищо Хвърля Хвърля ThreadInterruptedExceptionThreadInterruptedException

Join()Join() Start()Start()

Page 47: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt()

Join()Join() Извикващата нишка изчаква, докато Извикващата нишка изчаква, докато

извиканата приключиизвиканата приключи Може да се укаже таймаут (timeout)Може да се укаже таймаут (timeout)

Start()Start()

Page 48: Многонишково програмиране и синхронизация

Демонстрация #Демонстрация #55 Използване на Използване на Thread.Join()Thread.Join()

Page 49: Многонишково програмиране и синхронизация

По-важните членове на По-важните членове на ThreadThread public Thread( ThreadStart start);public Thread( ThreadStart start); Sleep()Sleep() Suspend()Suspend() Resume()Resume() IsAliveIsAlive IsBackgroundIsBackground IsThreadPoolThreadIsThreadPoolThread NameName PriorityPriority ThreadStateThreadState Abort()Abort() Interrupt()Interrupt() Join()Join()

Start()Start() Стартира посочената нишкаСтартира посочената нишка Операцията не е блокираща (връща Операцията не е блокираща (връща

управлението веднага)управлението веднага)

Page 50: Многонишково програмиране и синхронизация

Приоритет на нишкаПриоритет на нишка Повечето имплементации на Повечето имплементации на

многонишковост включват отличителното многонишковост включват отличителното качество "приоритет"качество "приоритет" Приоритетът указва колко важна е нишката Приоритетът указва колко важна е нишката

(колко време да й се отделя)(колко време да й се отделя) Важен е за планировчика (Важен е за планировчика (task scheduler) task scheduler)

Приоритетът в Приоритетът в .NET Framework.NET Framework Възможни стойностиВъзможни стойности

LowestLowest, , BelowNormalBelowNormal, , NormalNormal ( (по по подразбиране), подразбиране), AboveNormalAboveNormal, , HighestHighest

В В Win32 Win32 има и приоритет има и приоритет RealTimeRealTime OSOS не е длъжна да се съобразява с приоритета не е длъжна да се съобразява с приоритета

на нишките, но обикновено го правина нишките, но обикновено го прави

Page 51: Многонишково програмиране и синхронизация

ПриоритетПриоритет – – примерпримерclass FirstThread {class FirstThread { public void DoTask1() {public void DoTask1() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread1:job({0})",i);Console.WriteLine("Thread1:job({0})",i); }} public void DoTask2() {public void DoTask2() { for( int i=0; i<100; i++ )for( int i=0; i<100; i++ ) Console.WriteLine("Thread2:job({0})",i);Console.WriteLine("Thread2:job({0})",i); }}}}class Starterclass Starter static void Main(string[] args) {static void Main(string[] args) { FirstThread ft = new FirstThread();FirstThread ft = new FirstThread(); Thread t1 = new Thread(Thread t1 = new Thread( new ThreadStart(ft.DoTask1));new ThreadStart(ft.DoTask1)); Thread t2 = new Thread(Thread t2 = new Thread( new ThreadStart(ft.DoTask2));new ThreadStart(ft.DoTask2)); t1.Priority = ThreadPriority.Highest;t1.Priority = ThreadPriority.Highest; t1.Start();t1.Start(); t2.Start();t2.Start(); }}}}

Page 52: Многонишково програмиране и синхронизация

ПриоритетПриоритетРезултат:Резултат:Thread1:job(1)Thread1:job(1)Thread1:job(2)Thread1:job(2)Thread2:job(1)Thread2:job(1)Thread1:job(3)Thread1:job(3)............Thread1:job(97)Thread1:job(97)Thread1:job(98)Thread1:job(98)Thread2:job(85)Thread2:job(85)Thread1:job(99)Thread1:job(99)Thread2:job(86)Thread2:job(86)............Thread2:job(97)Thread2:job(97)Thread2:job(98)Thread2:job(98)Thread2:job(99)Thread2:job(99)

Page 53: Многонишково програмиране и синхронизация

ThreadStateThreadState Всяка нишка във всеки един момент е в Всяка нишка във всеки един момент е в

някое от състоянията на енумерацията някое от състоянията на енумерацията ThreadStateThreadState

Допуска се да бъде в няколко състояния Допуска се да бъде в няколко състояния едновременноедновременно

Енумерацията има атрибут Енумерацията има атрибут FlagsAttributeFlagsAttribute Това позволява побитово комбиниране на Това позволява побитово комбиниране на

стойностите й:стойностите й:if ((state & (Unstarted | Stopped)) == 0) if ((state & (Unstarted | Stopped)) == 0)

// implies Running// implies Running

Когато се създаде нишка е в състояние Когато се създаде нишка е в състояние UnstartedUnstarted Остава така докато не се извика Остава така докато не се извика StartStart()()

Page 54: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256)

Извикан е метода Извикан е метода Abort()Abort() Нишката е в състояние Нишката е в състояние StoppedStopped, ,

едновременно с едновременно с AbortedAborted AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 55: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128)

Методът Методът Abort()Abort() е бил извикане бил извикан Още не е получила Още не е получила ThreadAbortExceptionThreadAbortException, ,

което ще се опита да я прекратикоето ще се опита да я прекрати Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 56: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4)

Нишката е във фонов режимНишката е във фонов режим Променя се със свойството Променя се със свойството

Thread.IsBackgroundThread.IsBackground Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 57: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0)

Нишката е стартирана и не е блокиранаНишката е стартирана и не е блокирана Няма чакащо изключение Няма чакащо изключение

ThreadAbortedExceptionThreadAbortedException Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 58: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16)

Нишката е отговорила на заявка от Нишката е отговорила на заявка от Abort()Abort() илиили

Прекратила е работата си доброволноПрекратила е работата си доброволно StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 59: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1)

Поискано е било от нишката да спре Поискано е било от нишката да спре работаработа

Само за вътрешна употребаСамо за вътрешна употреба Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 60: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64)

Нишката е била преустановенаНишката е била преустановена Независимо колко пъти е извикан Независимо колко пъти е извикан

Suspend()Suspend(), , един един Resume()Resume() е достатъчене достатъчен SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 61: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2)

Извикан е метода Извикан е метода Suspend()Suspend() Изчаква се да стигне до стабилно Изчаква се да стигне до стабилно

състояние, за да се преустановисъстояние, за да се преустанови Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Page 62: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8)

НеНе е стартирана, стартира се със е стартирана, стартира се със Start()Start() След като се стартира нишката никога След като се стартира нишката никога

повече не може пак да е в това състояниеповече не може пак да е в това състояние WaitSleepJoin(32)WaitSleepJoin(32)

Page 63: Многонишково програмиране и синхронизация

Състоянията в Състоянията в ThreadStateThreadState Aborted(256)Aborted(256) AbortRequested(128)AbortRequested(128) Background(4)Background(4) Running(0)Running(0) Stopped(16)Stopped(16) StopRequested(1)StopRequested(1) Suspended(64)Suspended(64) SuspendRequested(2)SuspendRequested(2) Unstarted(8)Unstarted(8) WaitSleepJoin(32)WaitSleepJoin(32)

Нишката е блокиранаНишката е блокирана Става с един от методитеСтава с един от методите Thread.Wait()Thread.Wait(), ,

Thread.Sleep()Thread.Sleep(), , Thread.Join()Thread.Join()

Page 64: Многонишково програмиране и синхронизация

Прекратяване на нишкиПрекратяване на нишки За да се “убие” една нишка, се За да се “убие” една нишка, се

използва методът използва методът Thread.Abort()Thread.Abort() Thread.Abort()Thread.Abort() хвърля специалното хвърля специалното

изключение изключение ThreadAbortedExceptionThreadAbortedException Хвърля Хвърля ThreadStateExceptionThreadStateException, ако , ако

нишката вече е прекратенанишката вече е прекратена Изпълняват се Изпълняват се catchcatch и и finallyfinally на на

прекратената нишкапрекратената нишка Thread.ResetAbort()Thread.ResetAbort() не позволява на не позволява на

CLR да хвърли изключението отновоCLR да хвърли изключението отново Unmanaged code – изчакванеUnmanaged code – изчакване

Page 65: Многонишково програмиране и синхронизация

Прекратяване на нишки – примерПрекратяване на нишки – примерpublic class Backpublic class BackggroundThread {roundThread { public void public void DDoBackgroundJob() {oBackgroundJob() { trytry {{ // Нишката извършва някаква работа// Нишката извършва някаква работа }} catch(ThreadInterruptedException)catch(ThreadInterruptedException) {{ MessageBox.Show("Thread MessageBox.Show("Thread iinterruptednterrupted..");"); }} catch(ThreadAbortException) {catch(ThreadAbortException) { MessageBox.Show("ThreadMessageBox.Show("Thread aborted. aborted.");"); }} finallyfinally {{ MessageBox.Show("MessageBox.Show("FFinally blockinally block..");"); }} MessageBox.Show(MessageBox.Show("After finally block."After finally block.");"); }}}} ((примерът продължава)примерът продължава)

Page 66: Многонишково програмиране и синхронизация

Прекратяване на нишки – примерПрекратяване на нишки – пример

public class InterruptAbortDemopublic class InterruptAbortDemo{{ private Thread mBgThread;private Thread mBgThread;

public InterruptAbortDemo() {public InterruptAbortDemo() { bg = new BackgroundThread();bg = new BackgroundThread(); mBgThread = new Thread(newmBgThread = new Thread(new ThreadStart(bg.DoBackgroundJob));ThreadStart(bg.DoBackgroundJob)); mBgThread.IsBackground = true;mBgThread.IsBackground = true; mBgThread.Start();mBgThread.Start(); }}

private void btnSuspend_Click(...)private void btnSuspend_Click(...) {{ mBgThread.Suspend();mBgThread.Suspend(); }} ((примерът продължава)примерът продължава)

Page 67: Многонишково програмиране и синхронизация

Прекратяване на нишки – примерПрекратяване на нишки – пример

private void btnResume_Click(...)private void btnResume_Click(...) {{ mBgThread.Resume();mBgThread.Resume(); }}

private void btnInterrupt_Click(...)private void btnInterrupt_Click(...) {{ mBgThread.Interrupt();mBgThread.Interrupt(); }}

private void btnAbort_Click(...)private void btnAbort_Click(...) {{ mBgThread.Abort();mBgThread.Abort(); }}}}

Page 68: Многонишково програмиране и синхронизация

Демонстрация #Демонстрация #66 Използване на Използване на PriorityPriority, , StateState, ,

SuspendSuspend, , ResumeResume, , InterruptInterrupt и и AbortAbort

Page 69: Многонишково програмиране и синхронизация

Thread Local StorageThread Local Storage Контейнер, в който нишките могат да Контейнер, в който нишките могат да

съхраняват даннисъхраняват данни Нишка не може да достъпи данните Нишка не може да достъпи данните

на друга нишкана друга нишка Thread.AllocateNamedDataSlotThread.AllocateNamedDataSlot

Именуван контейнерИменуван контейнер Проблеми – уникални именаПроблеми – уникални имена

Thread.AllocateDataSlotThread.AllocateDataSlot Няма име, само referenceНяма име, само reference

Проблеми: две парчета код от една и Проблеми: две парчета код от една и съща нишка използват общ слотсъща нишка използват общ слот

Page 70: Многонишково програмиране и синхронизация

ThreadThread LocalLocal StorageStorage – пример – примерclass Threads {class Threads { public void CreateDataThread() {public void CreateDataThread() { LocalDataStoreSlot slot =LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("mySlot");Thread.AllocateNamedDataSlot("mySlot");

//Записваме важни данни в NamedSlot//Записваме важни данни в NamedSlot Thread.SetData(slot ,"IMPORTANT DATA");Thread.SetData(slot ,"IMPORTANT DATA"); // Suspend-ваме// Suspend-ваме Thread.CurrentThread.Suspend();Thread.CurrentThread.Suspend(); // Прочитаме отново данните// Прочитаме отново данните object myData = Thread.GetData("mySlot");object myData = Thread.GetData("mySlot"); }}

public void ReadDataThread() {public void ReadDataThread() { LocalDataStoreSlot slot =LocalDataStoreSlot slot = Thread.GetNamedDataSlot("mySlot");Thread.GetNamedDataSlot("mySlot"); // Опитваме се да променим информацията// Опитваме се да променим информацията Thread.SetData(slot, "BAD DATA");Thread.SetData(slot, "BAD DATA"); }}}} (примерът продължава)(примерът продължава)

Page 71: Многонишково програмиране и синхронизация

ThreadThread LocalLocal StorageStorage – пример – примерclass TLSDemoclass TLSDemo{{ static void Main(string[] args)static void Main(string[] args) {{ Threads threads = new Threads();Threads threads = new Threads(); Thread createData = new Thread( newThread createData = new Thread( new ThreadStart(threads.createDataThread) );ThreadStart(threads.createDataThread) ); createData.Start();createData.Start();

Thread readData = new Thread( newThread readData = new Thread( new ThreadStart(threads.readDataThread) );ThreadStart(threads.readDataThread) ); readData.Start();readData.Start(); readData.Join();readData.Join(); createData.Resume();createData.Resume(); }}}}

Page 72: Многонишково програмиране и синхронизация

Демонстрация #Демонстрация #77 ThreadLocalStorageThreadLocalStorage

Page 73: Многонишково програмиране и синхронизация

Thread-Relative Static FieldsThread-Relative Static Fields Като статична променлива, но има по Като статична променлива, но има по

една инстанция за всяка нишка на една инстанция за всяка нишка на програматапрограмата

Декларира се като статична Декларира се като статична променлива, но с атрибута променлива, но с атрибута [[ThreadStaticThreadStatic]]

Всяка нишка, която я използва трябва Всяка нишка, която я използва трябва да я инициализирада я инициализира

Не разчитайте на конструктора да Не разчитайте на конструктора да инициализира такива променливи, инициализира такива променливи, защото той се изпълнява в защото той се изпълнява в родителската нишка!родителската нишка!

Page 74: Многонишково програмиране и синхронизация

Thread-Relative Static Fields – Thread-Relative Static Fields – примерпример

class ThreadStatic {class ThreadStatic { static void Main(string[] args) {static void Main(string[] args) { for( int i=0; i<10; i++ ) {for( int i=0; i<10; i++ ) { new Thread(new ThreadStart(newnew Thread(new ThreadStart(new MyThread().MyThread().DDoTask)).Start();oTask)).Start(); }} }}}}

class MyThread {class MyThread { [ThreadStatic] public static int abc;[ThreadStatic] public static int abc; public MyThread() {public MyThread() { abc=42; abc=42; // // This runs in the main app. threadThis runs in the main app. thread }} public void public void DDoTask() {oTask() { abc++;abc++; Console.WriteLine("abc=Console.WriteLine("abc={0}{0}"", , abc);abc); }}}}

Page 75: Многонишково програмиране и синхронизация

Демонстрация #8Демонстрация #8 Използване на Използване на ThreadThread StaticStatic поле поле

Page 76: Многонишково програмиране и синхронизация

Неудобства на нишкитеНеудобства на нишките Самата имплементация на Самата имплементация на

многонишковост изисква ресурсимногонишковост изисква ресурси Добра практика е да не прекалявате с Добра практика е да не прекалявате с

използването на нишкиизползването на нишки Възможно е процесорът да използва Възможно е процесорът да използва

повече ресурси за управлението на повече ресурси за управлението на нишките отколкото за изпълнението имнишките отколкото за изпълнението им

Препоръчва се да използвате Препоръчва се да използвате ThreadPoolThreadPool когато е възможно когато е възможно

Следенето на много нишки е трудно Следенето на много нишки е трудно

Page 77: Многонишково програмиране и синхронизация

Споделени данни –Споделени данни – проблемипроблеми Race conditionRace condition

Две нишки едновременно достъпват Две нишки едновременно достъпват едни и същи данниедни и същи данни

Непредвидими резултатиНепредвидими резултати Например две нишки едновременно Например две нишки едновременно

изпълняват изпълняват i++ i++ на обща променлива на обща променлива ii DeadlockDeadlock

Състояние, в което две нишки се чакат Състояние, в което две нишки се чакат взаимно за освобождаване на взаимно взаимно за освобождаване на взаимно заети ресурсизаети ресурси

AA заема ресурса заема ресурса XX, , BB заема ресурса заема ресурса Y Y и и чака за чака за X,X, а а A A започва да чака за започва да чака за YY

Page 78: Многонишково програмиране и синхронизация

Race Condition – Race Condition – примерпримерusing System;using System;using System.Threading;using System.Threading;

class Accountclass Account{{ public int mBalance;public int mBalance;

public void Withdraw100()public void Withdraw100() {{ int oldBalance = mBalance;int oldBalance = mBalance; Console.WriteLine("Withdrawing 100...");Console.WriteLine("Withdrawing 100..."); Thread.Sleep(100);Thread.Sleep(100); int newBalance = oldBalance - 100;int newBalance = oldBalance - 100; mBalance = newBalance;mBalance = newBalance; }}}} (примерът продължава)(примерът продължава)

Page 79: Многонишково програмиране и синхронизация

Race ConditionRace Condition – пример – примерstatic void Main(string[] args)static void Main(string[] args){{ Account acc = new Account();Account acc = new Account(); acc.mBalance = 500;acc.mBalance = 500; Console.WriteLine("Console.WriteLine("Account balance = {0}Account balance = {0}"",, acc.mBalance);acc.mBalance); Thread user1 = new Thread( Thread user1 = new Thread( new ThreadStart(acc.Withdraw100) );new ThreadStart(acc.Withdraw100) ); Thread user2 = new Thread(Thread user2 = new Thread( new ThreadStart(acc.Withdraw100) );new ThreadStart(acc.Withdraw100) ); user1.Start();user1.Start(); user2.Start();user2.Start(); user1.Join();user1.Join(); user2.Join();user2.Join(); Console.WriteLine("Console.WriteLine("Account balance = {0}Account balance = {0}"",, acc.mBalance);acc.mBalance);}}

Page 80: Многонишково програмиране и синхронизация

Демонстрация Демонстрация ##99 Повреждане на данниПовреждане на данни

Page 81: Многонишково програмиране и синхронизация

Синхронизация – съдържаниеСинхронизация – съдържание МногозадачностМногозадачност НишкиНишки СинхронизацияСинхронизация

Най-доброто решениеНай-доброто решение ““Стратегии” за синхронизацияСтратегии” за синхронизация Synchronized ContextsSynchronized Contexts Synchronized code regionsSynchronized code regions MethodImplAttributeMethodImplAttribute Unmanaged Synchronization – Unmanaged Synchronization – WaitHandleWaitHandle Специални класове Специални класове

Класически синхронизационни проблемиКласически синхронизационни проблеми ThreadPoolThreadPool

Асинхронни извикванияАсинхронни извиквания

Page 82: Многонишково програмиране и синхронизация

Най-доброто решениеНай-доброто решение Най-добра сигурност при споделени Най-добра сигурност при споделени

данни в многонишкова среда е данни в многонишкова среда е липсата на споделени даннилипсата на споделени данни

Препоръчва се Препоръчва се Да се капсулират данните и ресурсите в Да се капсулират данните и ресурсите в

инстанции на обектиинстанции на обекти Тези обекти да не се споделят между Тези обекти да не се споделят между

нишкинишки

Когато това е невъзможно, Когато това е невъзможно, .NET .NET Framework, Framework, предоставя механизми за предоставя механизми за синхронизация на достъпа до даннисинхронизация на достъпа до данни

Page 83: Многонишково програмиране и синхронизация

““Стратегии” за синхронизацияСтратегии” за синхронизация

Синхронизирани контексти Синхронизирани контексти (Synchronized Contexts)(Synchronized Contexts)

Синхронизирани “пасажи” код Синхронизирани “пасажи” код (Synchronized code regions)(Synchronized code regions)

[MethodImplAttribute [MethodImplAttribute (MethodImplOptions.Synchronized)](MethodImplOptions.Synchronized)] над имплементацията на методнад имплементацията на метод

Unmanaged синхронизация Unmanaged синхронизация Класове за фина, ръчно настроена Класове за фина, ръчно настроена

(custom) синхронизация с обекти на OS(custom) синхронизация с обекти на OS

Page 84: Многонишково програмиране и синхронизация

Synchronized ContextsSynchronized Contexts Използва се Използва се SynchronizationAttributeSynchronizationAttribute

за обекти, наследяващи за обекти, наследяващи ContextBoundObjectContextBoundObject обекти, които оперират в един контекстобекти, които оперират в един контекст

Всички нишки в този контекст достъпват Всички нишки в този контекст достъпват методите на инстанции на такива обекти методите на инстанции на такива обекти последователнопоследователно

Статичните членове не са предпазениСтатичните членове не са предпазени Не се поддържа синхронизиране на Не се поддържа синхронизиране на

специфични “отрязъци” от код – специфични “отрязъци” от код – синхронизира цял классинхронизира цял клас

Page 85: Многонишково програмиране и синхронизация

Synchronized ContextsSynchronized Contexts – пример – пример[SynchronizationAttribute][SynchronizationAttribute]class CBO : ContextBoundObjectclass CBO : ContextBoundObject{{ public void DoSomeTask1()public void DoSomeTask1() {{ Console.WriteLine("Job1 started.");Console.WriteLine("Job1 started."); Thread.Sleep(2000);Thread.Sleep(2000); Console.WriteLine("Job1 finished.\n");Console.WriteLine("Job1 finished.\n"); }}

public void DoSomeTask2()public void DoSomeTask2() {{ Console.WriteLine("Job2 started.");Console.WriteLine("Job2 started."); Thread.Sleep(1500);Thread.Sleep(1500); Console.WriteLine("Job2 finished.\n");Console.WriteLine("Job2 finished.\n"); }}}} ((примерът продължава)примерът продължава)

Page 86: Многонишково програмиране и синхронизация

Synchronized ContextsSynchronized Contexts – пример – пример

static void Main()static void Main(){{ CBO syncClass = new CBO();CBO syncClass = new CBO(); Console.WriteLine("Started 6 threads:\n" +Console.WriteLine("Started 6 threads:\n" + "3 doing Job1 and 3 doing Job2.\n\n");"3 doing Job1 and 3 doing Job2.\n\n"); for (int i=0; i<6; i++)for (int i=0; i<6; i++) {{ Thread t;Thread t; if (i%2==0) if (i%2==0) t = new Thread( new ThreadStart(t = new Thread( new ThreadStart( syncClass.DoSomeTask1) );syncClass.DoSomeTask1) ); elseelse t = new Thread( new ThreadStart(t = new Thread( new ThreadStart( syncClass.DoSomeTask2) );syncClass.DoSomeTask2) ); t.Start();t.Start(); }}}}

Page 87: Многонишково програмиране и синхронизация

Демонстрация #10Демонстрация #10 Синхронизация чрез Синхронизация чрез

ContextBoundObjectContextBoundObject

Page 88: Многонишково програмиране и синхронизация

Критични секцииКритични секцииlock (obj) {lock (obj) { //..code.. //..code..}}

Управлявана (managed) реализацияУправлявана (managed) реализация Може да се ползва и за статични Може да се ползва и за статични

членове на класоветечленове на класовете Синхронизира се изпълнението Синхронизира се изпълнението

само частта, която е застрашенасамо частта, която е застрашена Нарича се критична секцияНарича се критична секция

Monitor.TryEnter();Monitor.TryEnter();

Monitor.Enter(obj);Monitor.Enter(obj);try { /*..code..*/ }try { /*..code..*/ }finally { Monitor.Exit(obj); }finally { Monitor.Exit(obj); }

Page 89: Многонишково програмиране и синхронизация

Критични секции – примерКритични секции – примерpublic class MonitorEnterExitpublic class MonitorEnterExit{{ private int mCounter;private int mCounter;

public void CriticalSection()public void CriticalSection() {{ Monitor.Enter(this);Monitor.Enter(this); mCounter = 0;mCounter = 0; trytry {{ for(int i = 1; i <= 5; i++) { for(int i = 1; i <= 5; i++) { Console.Write(++mCounter);Console.Write(++mCounter); Thread.Sleep(1000);Thread.Sleep(1000); }} }} finallyfinally {{ Monitor.Exit(this);Monitor.Exit(this); }} }} (примерът продължава)(примерът продължава)

Page 90: Многонишково програмиране и синхронизация

Критични секции – примерКритични секции – пример sstatic void Main() { tatic void Main() { MonitorEnterExit meMonitorEnterExit meee = new MonitorEnterExit(); = new MonitorEnterExit(); Thread Thread thread1thread1 = new Thread(new = new Thread(new ThreadStart(mee.CriticalSection)); ThreadStart(mee.CriticalSection)); thread1thread1.Start( );.Start( ); Thread Thread thread2thread2 = new Thread(new = new Thread(new ThreadStart(mee.CriticalSection)); ThreadStart(mee.CriticalSection)); thread2thread2.Start( );.Start( ); }}}}

// Резултат: 1234512345// Резултат: 1234512345

// Резултат без синхронизация: 1123456789// Резултат без синхронизация: 1123456789

Page 91: Многонишково програмиране и синхронизация

Демонстрация #1Демонстрация #111 Работа с критични секцииРабота с критични секции

Page 92: Многонишково програмиране и синхронизация

Няколко важни методаНяколко важни метода Monitor.Wait(object)Monitor.Wait(object)

Освобождава монитора на обекта и Освобождава монитора на обекта и блокира нишката докато не го получиблокира нишката докато не го получи

Може да се задава Може да се задава TimeoutTimeout Нишката се нарежда на waiting queueНишката се нарежда на waiting queue Чака Чака Pulse(object)Pulse(object), , PulseAll(object)PulseAll(object)

Monitor.Pulse(object)Monitor.Pulse(object) Нишката преминава в ready queueНишката преминава в ready queue

(има право да вземе монитора на обект)(има право да вземе монитора на обект) Вика се само от текущия собственик на Вика се само от текущия собственик на

монитора на обекта (от критична секция)монитора на обекта (от критична секция) Monitor.PulseAll(object)Monitor.PulseAll(object)

Page 93: Многонишково програмиране и синхронизация

Wait()Wait() и и Pulse()Pulse() – – примерпример

public class WaitPulsepublic class WaitPulse{{ private object mSync;private object mSync; private string mName;private string mName;

public WaitPulse(string aName,public WaitPulse(string aName, object aSync)object aSync) {{ mName = aName;mName = aName; mSync = aSync;mSync = aSync; }} ((примерът продължава)примерът продължава)

Имаме две нишки, които съвместно Имаме две нишки, които съвместно изпълняват някаква задачаизпълняват някаква задача

Когато едната прави нещо, другата я Когато едната прави нещо, другата я изчаква и обратнотоизчаква и обратното

Page 94: Многонишково програмиране и синхронизация

Wait()Wait() и и Pulse()Pulse() – – примерпример public void DoJob()public void DoJob() {{ lock (mSync)lock (mSync) {{ Monitor.Pulse(mSync);Monitor.Pulse(mSync); for(int i = 1; i <= for(int i = 1; i <= 33; i++); i++) {{ Console.WriteLine("{0}: Pulsе", mName);Console.WriteLine("{0}: Pulsе", mName); Monitor.Pulse(mSync);Monitor.Pulse(mSync);

Console.WriteLine("{0}: Wait", mName);Console.WriteLine("{0}: Wait", mName); Monitor.Wait(mSync);Monitor.Wait(mSync);

Console.WriteLine("{0}: WokeUp", mName);Console.WriteLine("{0}: WokeUp", mName); Thread.Sleep(1000);Thread.Sleep(1000); }} }} }}}} ((примерът продължава)примерът продължава)

Page 95: Многонишково програмиране и синхронизация

Wait()Wait() и и Pulse()Pulse() – – примерпримерpublic class WaitPulseDemopublic class WaitPulseDemo{{ public static void Main(String[] args)public static void Main(String[] args) {{ object sync = new object();object sync = new object();

WaitPulse wp1 = new WaitPulse(WaitPulse wp1 = new WaitPulse( "WaitPulse1", sync);"WaitPulse1", sync); Thread thread1 = new Thread(Thread thread1 = new Thread( new ThreadStart(wp1.DoJob));new ThreadStart(wp1.DoJob)); thread1.Start();thread1.Start();

WaitPulse wp2 = new WaitPulse(WaitPulse wp2 = new WaitPulse( "WaitPulse2", sync);"WaitPulse2", sync); Thread thread2 = new Thread(Thread thread2 = new Thread( new ThreadStart(wp2.DoJob));new ThreadStart(wp2.DoJob)); thread2.Start();thread2.Start(); }}}}

Page 96: Многонишково програмиране и синхронизация

Демонстрация #12Демонстрация #12 Работа с Работа с Wait()Wait() и и Pulse()Pulse()

Page 97: Многонишково програмиране и синхронизация

Прилича на Прилича на locklock върху цял метод върху цял метод Може да синхронизира и Може да синхронизира и static static

членовечленове

[MethodImplAttribute [MethodImplAttribute (MethodImplOptions.Synchronized)](MethodImplOptions.Synchronized)]

[MethodImpl(MethodImplOptions.Synchronized)][MethodImpl(MethodImplOptions.Synchronized)] public void public void DDoSomeTask1()oSomeTask1(){{ Console.WriteLine("job1 started");Console.WriteLine("job1 started"); forfor (int i=0; i<1(int i=0; i<10000000000; i++)00000000; i++) Math.Sqrt(i);Math.Sqrt(i); Console.WriteLine("Console.WriteLine("JJob1 doneob1 done..\n");\n");}}

Page 98: Многонишково програмиране и синхронизация

Unmanaged SynchronizationUnmanaged Synchronization WaitHandleWaitHandle

Unmanaged механизъм за Unmanaged механизъм за синхронизациясинхронизация

Използва обекти на операционната Използва обекти на операционната система – за изчакване на ресурсисистема – за изчакване на ресурси

Предоставя възможности отвъд тези на Предоставя възможности отвъд тези на CLR – CLR – WaitAll()WaitAll(), , WaitAny()WaitAny()

Не се препоръчва – не е managedНе се препоръчва – не е managed Има няколко наследника:Има няколко наследника:

MutexMutex AutoResetEventAutoResetEvent ManualResetEventManualResetEvent

Page 99: Многонишково програмиране и синхронизация

Класът Класът WaitHandleWaitHandle Неговите методи се използват за Неговите методи се използват за

изчакване на събитияизчакване на събития Състояния: signaled, nonsignaledСъстояния: signaled, nonsignaled WaitAll() (static)WaitAll() (static)

Изчаква сигнал от всички събития от масивИзчаква сигнал от всички събития от масив

WaitAny() (static)WaitAny() (static) Изчаква първото получило сигналИзчаква първото получило сигнал

WaitOne()WaitOne() Изчаква текущото събитие да приключиИзчаква текущото събитие да приключи

Прилики и разлики с класаПрилики и разлики с класа Monitor Monitor

Page 100: Многонишково програмиране и синхронизация

MutexMutex Наследник на Наследник на WaitHandleWaitHandle Примитив за синхронизация на OSПримитив за синхронизация на OS Енкапсулира Win32 synchronization Енкапсулира Win32 synchronization

handleshandles Mutex.WaitOne();Mutex.WaitOne(); Mutex.ReleaseMutex();Mutex.ReleaseMutex();

Трябва да се извика, същия брой пъти Трябва да се извика, същия брой пъти като като Mutex.WaitOne();Mutex.WaitOne();

WaitHandle.WaitAll()WaitHandle.WaitAll() – изчаква – изчаква два или няколко handle-aдва или няколко handle-a

Page 101: Многонишково програмиране и синхронизация

MutexMutex – пример – примерclass MutexDemoclass MutexDemo{{ Mutex mMutex;Mutex mMutex; public MutexDemo(Mutex aMutex)public MutexDemo(Mutex aMutex) {{ mMutex = aMutex;mMutex = aMutex; }} public void PerformSomeTask()public void PerformSomeTask() {{ m.WaitOne();m.WaitOne(); Console.WriteLine("\nJob started...");Console.WriteLine("\nJob started..."); for( int i=0; i<10; i++)for( int i=0; i<10; i++) {{ Thread.Sleep(100);Thread.Sleep(100); Console.Write("|");Console.Write("|"); }} Console.WriteLine("\nJob finished.");Console.WriteLine("\nJob finished."); m.ReleaseMutex();m.ReleaseMutex(); }}}}

Page 102: Многонишково програмиране и синхронизация

Демонстрация #13Демонстрация #13 Синхронизация с Синхронизация с MutexMutex

Page 103: Многонишково програмиране и синхронизация

AutoResetEventAutoResetEvent,,ManualResetEventManualResetEvent

Наследници на Наследници на WaitHandleWaitHandle Примитиви за синхронизацияПримитиви за синхронизация Енкапсулират Win32 synchronization Енкапсулират Win32 synchronization

handleshandles Сигнализиране със Сигнализиране със Set()Set()

AutoResetEventAutoResetEvent сигнализира само сигнализира само първия манипулатор(handle)първия манипулатор(handle) Минава автоматично в nonsignaled stateМинава автоматично в nonsignaled state

ManualResetEvent()ManualResetEvent() сигнализира сигнализира всички чакащи манипулаторивсички чакащи манипулатори Остава в signaled state, докато някой не го Остава в signaled state, докато някой не го

променипромени

Page 104: Многонишково програмиране и синхронизация

AutoResetEvent/AutoResetEvent/ManualResetEventManualResetEventusing System;using System;

using System.Threading;using System.Threading;class OneWhoWaitsclass OneWhoWaits{{ WaitHandle mWaitHandle;WaitHandle mWaitHandle; int mWaitTime;int mWaitTime; public OneWhoWaits(WaitHandle aWaitHandle,public OneWhoWaits(WaitHandle aWaitHandle, int waitTime )int waitTime ) {{ mWaitHandle = aWaitHandle;mWaitHandle = aWaitHandle; mWaitTime = mWaitTime;mWaitTime = mWaitTime; }} public void performSomeTask()public void performSomeTask() {{ Thread.Sleep(mWaitTime);Thread.Sleep(mWaitTime); Console.WriteLine("Thread {0} waiting",Console.WriteLine("Thread {0} waiting", Thread.CurrentThread.GetHashCode());Thread.CurrentThread.GetHashCode()); mWaitHandle.WaitOne();mWaitHandle.WaitOne(); }}}} (примерът продължава)(примерът продължава)

Page 105: Многонишково програмиране и синхронизация

AutoResetEvent/AutoResetEvent/ManualResetEventManualResetEventclass MainClassclass MainClass

{{ static void Main()static void Main() {{ ManualResetEvent evnt = newManualResetEvent evnt = new ManualResetEvent(false);ManualResetEvent(false); for (int i=0; i<10; i++ )for (int i=0; i<10; i++ ) {{ OneWhoWaits oww = OneWhoWaits oww = new OneWhoWaits(evnt, (i+1)*500);new OneWhoWaits(evnt, (i+1)*500); Thread thread = new Thread(Thread thread = new Thread( new ThreadStart(oww.performSomeTask));new ThreadStart(oww.performSomeTask)); thread.Start();thread.Start(); }} for (int i=0; i<10; i++)for (int i=0; i<10; i++) {{ Console.ReadLine();Console.ReadLine(); evnt.Set();evnt.Set(); }} }}}}

Page 106: Многонишково програмиране и синхронизация

Демонстрация #14Демонстрация #14 Синхронизация с Синхронизация с AutoResetEventAutoResetEvent и и

ManualResetEventManualResetEvent

Page 107: Многонишково програмиране и синхронизация

Специални класовеСпециални класове System.Threading.InterlockedSystem.Threading.Interlocked

Атомарни операцииАтомарни операции System.Threading.ThreadPoolSystem.Threading.ThreadPool

Бърз достъп до нишкиБърз достъп до нишки Преизползваемост на нишкитеПреизползваемост на нишките Програмистът не се грижи за живота на Програмистът не се грижи за живота на

нишкитенишките ( (създаване / унищожаване)създаване / унищожаване) System.Threading.ReaderWriterLockSystem.Threading.ReaderWriterLock

Класически синхронизационни Класически синхронизационни проблеми – Reader/Writer Problemпроблеми – Reader/Writer Problem

Synchronized WrappersSynchronized Wrappers

Page 108: Многонишково програмиране и синхронизация

System.Threading.InterlockedSystem.Threading.Interlocked

Осигурява изпълнение на атомарни Осигурява изпълнение на атомарни

операции – увеличение с 1, намаление с операции – увеличение с 1, намаление с

1, размяна, сравнение и др.1, размяна, сравнение и др.

Няма нужда синхронизация на Няма нужда синхронизация на

споделените даннисподелените данни

В по-простите случаи синхронизацията В по-простите случаи синхронизацията

може да се избегне с тези методиможе да се избегне с тези методи

Методите не хвърлят изключенияМетодите не хвърлят изключения

Page 109: Многонишково програмиране и синхронизация

System.Threading.InterlockedSystem.Threading.Interlocked Increment/DecrementIncrement/Decrement

Атомарна операция за разлика от Атомарна операция за разлика от i++/i--i++/i--

ExchangeExchange Записва стойността на вторият Записва стойността на вторият

параметър в първия, връща оригиналапараметър в първия, връща оригинала CompareExchangeCompareExchange

Има три параметъраИма три параметъра Проверява дали първият и третият са Проверява дали първият и третият са

равни, ако да, записва втория в първияравни, ако да, записва втория в първия Използва се при работа с временни Използва се при работа с временни

променливипроменливи

Page 110: Многонишково програмиране и синхронизация

InterlockedInterlocked – пример – примерclass TestInterlockedIncrementclass TestInterlockedIncrement{{ static long mUnsafeCounter = 0;static long mUnsafeCounter = 0; static long mSafeCounter = 0;static long mSafeCounter = 0;

private static void DoTask()private static void DoTask() {{ while (true)while (true) {{ mUnsafeCounter++;mUnsafeCounter++; Interlocked.Increment(ref mSafeCounter);Interlocked.Increment(ref mSafeCounter);

if (mSafeCounter % 10000000 == 0)if (mSafeCounter % 10000000 == 0) {{ Console.WriteLine("Safe={0}, Unsafe={1}",Console.WriteLine("Safe={0}, Unsafe={1}", mSafeCounter, mUnsafeCounter);mSafeCounter, mUnsafeCounter); }} }} }}

Page 111: Многонишково програмиране и синхронизация

static void Main(string[] args)static void Main(string[] args) {{ for (int i=0; i<for (int i=0; i<55; i++); i++) {{ Thread thread = new Thread(Thread thread = new Thread( new ThreadStart(DoTask));new ThreadStart(DoTask)); thread.Start();thread.Start(); }} }}}}

// // Резултат:Резултат:// Safe=10000000, Unsafe=5846325// Safe=10000000, Unsafe=5846325// Safe=20000000, Unsafe=15846326// Safe=20000000, Unsafe=15846326// Safe=30000000, Unsafe=25846326// Safe=30000000, Unsafe=25846326// Safe=40000000, Unsafe=35846325// Safe=40000000, Unsafe=35846325// Safe=50000000, Unsafe=41356463// Safe=50000000, Unsafe=41356463// ...// ...

InterlockedInterlocked – пример – пример

Page 112: Многонишково програмиране и синхронизация

Thread PoolingThread Pooling Много нишки прекарват по-голямата Много нишки прекарват по-голямата

част от живота си спейки част от живота си спейки ((ThreadState.WaitSleepJoinThreadState.WaitSleepJoin) ) или или чакайки някакво събитиечакайки някакво събитие

Други се “събуждат” само за малки Други се “събуждат” само за малки периоди, за да проверят истинността периоди, за да проверят истинността на някакво условие или за да на някакво условие или за да свършат нещо дребносвършат нещо дребно

Поддържането на много неактивни Поддържането на много неактивни нишки е излишно, неефективно и нишки е излишно, неефективно и консумира ресурсиконсумира ресурси

Page 113: Многонишково програмиране и синхронизация

ThreadThread PoolingPooling TP TP е подход за намаляване на товара при е подход за намаляване на товара при

създаване и унищожаване на нишкисъздаване и унищожаване на нишки При При TP TP се създават група нишки в началото се създават група нишки в началото

на многонишково приложениена многонишково приложение Наричат се “работни нишки” (Наричат се “работни нишки” (worker worker

threads)threads) Всяка нишка “живее” в т.нар. Всяка нишка “живее” в т.нар. Thread PoolThread Pool При нова задача, се използва При нова задача, се използва worker threadworker thread, ,

след това се връща обратно в пуласлед това се връща обратно в пула TP TP се грижи за живота и разпределението се грижи за живота и разпределението

на задачите върху нишкитена задачите върху нишките Използващият нишки се освобождава от Използващият нишки се освобождава от

този товартози товар

Page 114: Многонишково програмиране и синхронизация

System.Threading.ThreadPoolSystem.Threading.ThreadPool .NET Framework имплементира механизма .NET Framework имплементира механизма

Thread Pooling в класа Thread Pooling в класа ThreadPoolThreadPool Използва се, когато трябва да се свършат Използва се, когато трябва да се свършат

много на брой кратки задачи, които могат много на брой кратки задачи, които могат да работят паралелнода работят паралелно

Задачите се нареждат на опашка и се Задачите се нареждат на опашка и се изпълняват по няколко едновременно изпълняват по няколко едновременно (според броя worker threads)(според броя worker threads)

По подразбиране в Thread Pool-ът има По подразбиране в Thread Pool-ът има лимит от 25 нишки на процесорлимит от 25 нишки на процесор

Един процес може да има само един Thread Един процес може да има само един Thread Pool – той е общ за всички App DomainsPool – той е общ за всички App Domains

Page 115: Многонишково програмиране и синхронизация

System.Threading.ThreadPoolSystem.Threading.ThreadPool Thread PoolThread Pool-ът за даден процес се създава -ът за даден процес се създава

се при първото:се при първото: извикване на извикване на QueueUserWorkItemQueueUserWorkItem регистриране на таймер регистриране на таймер регистриране на изчакващарегистриране на изчакваща операция с операция с

callbackcallback метод метод .NET Framework .NET Framework използва използва Thread Pooling Thread Pooling заза::

асинхронни извикванияасинхронни извиквания асинхронен вход/изходасинхронен вход/изход работа с таймериработа с таймери работа със сокетиработа със сокети изчакващи операцииизчакващи операции

Page 116: Многонишково програмиране и синхронизация

System.Threading.ThreadPoolSystem.Threading.ThreadPool

Ако дадена задача е в Ако дадена задача е в ThreadThread PoolPool, не , не може да се премахне от негоможе да се премахне от него

ThreadThread Pooling Pooling позволява на позволява на OS OS да да оптимизира използването на нишки, оптимизира използването на нишки, тъй като броят им е постоянентъй като броят им е постоянен

Случаи, в които НЕ се препоръчва Случаи, в които НЕ се препоръчва използването на използването на ThreadThread PoolPool Ако е нужна контролираща нишкаАко е нужна контролираща нишка При задачи, отнемащи много време – може При задачи, отнемащи много време – може

да се блокират другите задачида се блокират другите задачи Ако има нужда от синхронизацияАко има нужда от синхронизация

Page 117: Многонишково програмиране и синхронизация

ThreadPool.QueueUserWorkItemThreadPool.QueueUserWorkItemclass ThreadPoolDemoclass ThreadPoolDemo{{ public static void LongTask(object aParam)public static void LongTask(object aParam) {{ Console.WriteLine("Started: {0}.", aParam);Console.WriteLine("Started: {0}.", aParam); Thread.Sleep(500);Thread.Sleep(500); Console.WriteLine("Finished: {0}.", aParam);Console.WriteLine("Finished: {0}.", aParam); }}

static void Main()static void Main() {{ for (int i=1; i<=100; i++)for (int i=1; i<=100; i++) {{ string taskName = "Task" + i;string taskName = "Task" + i; ThreadPool.QueueUserWorkItem(newThreadPool.QueueUserWorkItem(new WaitCallback(LongTask), taskName);WaitCallback(LongTask), taskName); }}

Console.ReadLine();Console.ReadLine(); }}}}

Page 118: Многонишково програмиране и синхронизация

Демонстрация #15Демонстрация #15 Изпълнение на задачи с Изпълнение на задачи с Thread PoolThread Pool

Page 119: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitThreadPool.RegisterWaitForSingleObjectForSingleObject

Регистрира делегат, който чака за Регистрира делегат, който чака за събитие (да бъде сигнализиран)събитие (да бъде сигнализиран)

Активира се при:Активира се при: сигнализиранесигнализиране при настъпване на зададен при настъпване на зададен timeouttimeout

Процесът по изчакване и извикване Процесът по изчакване и извикване се управлява се от се управлява се от Thread PoolThread Pool-а-а

Може да настрои да се изпълнява Може да настрои да се изпълнява делегатът многократноделегатът многократно

Page 120: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent ev =new AutoResetEvent(false);AutoResetEvent ev =new AutoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev, new WaitOrTimerCallback(WaitProc),ev, new WaitOrTimerCallback(WaitProc), param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaling.");Console.WriteLine("signaling."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("unregister wait");Console.WriteLine("unregister wait"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object param, bool public static void WaitProc(object param, bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 121: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent ev =new AutoResetEvent(false);AutoResetEvent ev =new AutoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev, ev, new WaitOrTimerCallback(WaitProc)new WaitOrTimerCallback(WaitProc),, param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaling.");Console.WriteLine("signaling."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("unregister wait");Console.WriteLine("unregister wait"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static public static void WaitProc(object param, bool void WaitProc(object param, bool timedOut)timedOut) { { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 122: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, 1000, false param, 1000, false );); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 123: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( evev,, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 124: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc)new WaitOrTimerCallback(WaitProc),, param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 125: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), paramparam, 1000, false );, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(public static void WaitProc(object object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 126: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, param, 10001000, false );, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 127: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, 1000, param, 1000, falsefalse ); ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 128: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle rRegisteredWaitHandle r = = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 129: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, , bool bool timedOuttimedOut) {) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 130: Многонишково програмиране и синхронизация

ThreadPool.RegisterWaitForSingleObjectThreadPool.RegisterWaitForSingleObjectusing ...using ...public class Example {public class Example { public static void Main(string[] args) {public static void Main(string[] args) { AutoResetEvent evAutoResetEvent ev =new=new A AutoResetEvent(false);utoResetEvent(false); object param = "some param";object param = "some param"; RegisteredWaitHandle r =RegisteredWaitHandle r = ThreadPool.RegisterWaitForSingleObject(ThreadPool.RegisterWaitForSingleObject( ev,ev, new WaitOrTimerCallback(WaitProc),new WaitOrTimerCallback(WaitProc), param, 1000, false );param, 1000, false ); Console.ReadLine();Console.ReadLine(); Console.WriteLine("signaConsole.WriteLine("signalingling.");."); ev.Set();ev.Set(); Console.ReadLine();Console.ReadLine(); Console.WriteLine("Console.WriteLine("unregister waitunregister wait");"); r.Unregister(ev);r.Unregister(ev); Console.ReadLine();Console.ReadLine(); }} public static void WaitProc(object public static void WaitProc(object paramparam, bool , bool timedOut) {timedOut) { string cause = "SIGNALED";string cause = "SIGNALED"; if (timedOut)if (timedOut) cause = "TIMED OUT";cause = "TIMED OUT"; Console.WriteLine("WaitProc executes;cause =Console.WriteLine("WaitProc executes;cause = {0}", cause);{0}", cause); }}}}

Page 131: Многонишково програмиране и синхронизация

Демонстрация #16Демонстрация #16 RegisterWaitForSingleObjectRegisterWaitForSingleObject

Page 132: Многонишково програмиране и синхронизация

Класически синхр. проблемиКласически синхр. проблеми The Producer-Consumer ProblemThe Producer-Consumer Problem

Един консуматор и един производител Един консуматор и един производител споделят общсподелят общa a опашка (опашка (shared queue)shared queue)

Изисквания:Изисквания: Ако опашката е празна, консуматорът Ако опашката е празна, консуматорът

блокира докато се появи нещо в неяблокира докато се появи нещо в нея Ако опашката е пълна, производителят Ако опашката е пълна, производителят

блокира докато не се опразни мястоблокира докато не се опразни място Производителят и консуматорът не могат да Производителят и консуматорът не могат да

достъпват опашката едновременнодостъпват опашката едновременно Пример: пощенска кутияПример: пощенска кутия Нарича се още Нарича се още bounded buffer problembounded buffer problem

Няма стандартен клас в .Няма стандартен клас в .NETNET

Page 133: Многонишково програмиране и синхронизация

The Readers-Writers ProblemThe Readers-Writers Problem Един или повече четеца и един или Един или повече четеца и един или

повече писеца достъпват общ ресурсповече писеца достъпват общ ресурс Пример: достъп до общ файл в OSПример: достъп до общ файл в OS Условия на Бернщайн:Условия на Бернщайн:

Няколко четци могат да достъпват общия Няколко четци могат да достъпват общия ресурсресурс

Когато писец достъпва ресурса, нито четец Когато писец достъпва ресурса, нито четец нито друг писец може да го достъпванито друг писец може да го достъпва

Очаква се нито един писец/четец да не чака Очаква се нито един писец/четец да не чака безкрайно дълго за споделения ресурсбезкрайно дълго за споделения ресурс

В .NET – В .NET – ReaderWriterLockReaderWriterLock

Класически синхр. проблемиКласически синхр. проблеми

Page 134: Многонишково програмиране и синхронизация

System.Threading.ReaderWriterLockSystem.Threading.ReaderWriterLock

Имплементира най-популярния Имплементира най-популярния синхронизационен проблем – синхронизационен проблем – Reader/Writer ProblemReader/Writer Problem

IsReaderLockHeldIsReaderLockHeld IsWriterLockHeldIsWriterLockHeld AcquireReaderLockAcquireReaderLock AcquireWriterLockAcquireWriterLock ReleaseReaderLockReleaseReaderLock ReleaseWriterLockReleaseWriterLock

Page 135: Многонишково програмиране и синхронизация

System.Threading.ReaderWriterLockSystem.Threading.ReaderWriterLockclass Resource {class Resource { ReaderWriterLock rwl = new ReaderWriterLock();ReaderWriterLock rwl = new ReaderWriterLock(); public void Read() {public void Read() { rwl.AcquireReaderLock(Timeout.Infinite);rwl.AcquireReaderLock(Timeout.Infinite); try {try { // // MMany can read, writers any can read, writers are are blockedblocked }} finally {finally { rwl.ReleaseReaderLock();rwl.ReleaseReaderLock(); }} }} public void Write() {public void Write() { rwl.AcquireWriterLock(Timeout.Infinite);rwl.AcquireWriterLock(Timeout.Infinite); try {try { // // OOne can write, ne can write, rreaders blockedeaders blocked }} finally {finally { rwl.ReleaseWriterLock();rwl.ReleaseWriterLock(); }} }}}}

Page 136: Многонишково програмиране и синхронизация

The Dining Philosophers The Dining Philosophers ProblemProblem Няколко философа стоятНяколко философа стоят

около кръгла маса и сеоколо кръгла маса и сехранят или мислятхранят или мислят

Когато се хранятКогато се хранят,, се нуждаят се нуждаяти от двете клечки от двете ими от двете клечки от двете имстранистрани

Условия:Условия: Не трябва никой философ да умре от гладНе трябва никой философ да умре от глад Не трябва да се позволява Не трябва да се позволява deadlock – deadlock – когато когато

всеки философ има по една клечка и чака за всеки философ има по една клечка и чака за другатадругата

Класически синхр. проблемиКласически синхр. проблеми

Page 137: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriterclass CustomReaderWriterclass CustomReaderWriter{{ private int mReaders = 0;private int mReaders = 0; private bool mIsWriting = false;private bool mIsWriting = false; public void Read()public void Read() {{ lock( this )lock( this ) {{ whilewhile (mIsWriting) Monitor.Wait( this );(mIsWriting) Monitor.Wait( this ); mReaders++;mReaders++; }}

//...READING TAKES PLACE HERE...//...READING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mReaders--;mReaders--; if( mReaders == 0 ) Monitor.Pulse(this);if( mReaders == 0 ) Monitor.Pulse(this); }} }} (примерът продължава)(примерът продължава)

Page 138: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriterclass CustomReaderWriterclass CustomReaderWriter{{ private int mReaders = 0;private int mReaders = 0; private bool mIsWriting = false;private bool mIsWriting = false; public void Read()public void Read() {{ lock( this )lock( this ) {{ whilewhile (mIsWriting) Monitor.Wait( this );(mIsWriting) Monitor.Wait( this ); mReaders++;mReaders++; }}

//...READING TAKES PLACE HERE...//...READING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mReaders--;mReaders--; if( mReaders == 0 ) Monitor.Pulse(this);if( mReaders == 0 ) Monitor.Pulse(this); }} }} (примерът продължава)(примерът продължава)

Page 139: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriterclass CustomReaderWriterclass CustomReaderWriter{{ private int mReaders = 0;private int mReaders = 0; private bool mIsWriting = false;private bool mIsWriting = false; public void Read()public void Read() {{ lock( this )lock( this ) {{ whilewhile (mIsWriting) Monitor.Wait( this );(mIsWriting) Monitor.Wait( this ); mReaders++;mReaders++; }}

//...READING TAKES PLACE HERE...//...READING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mReaders--;mReaders--; if( mReaders == 0 ) Monitor.Pulse(this);if( mReaders == 0 ) Monitor.Pulse(this); }} }} (примерът продължава)(примерът продължава)

Page 140: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriterclass CustomReaderWriterclass CustomReaderWriter{{ private int mReaders = 0;private int mReaders = 0; private bool mIsWriting = false;private bool mIsWriting = false; public void Read()public void Read() {{ lock( this )lock( this ) {{ whilewhile (mIsWriting) Monitor.Wait( this );(mIsWriting) Monitor.Wait( this ); mReaders++;mReaders++; }}

//...READING TAKES PLACE HERE...//...READING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mReaders--;mReaders--; if( mReaders == 0 ) Monitor.Pulse(this);if( mReaders == 0 ) Monitor.Pulse(this); }} }} (примерът продължава)(примерът продължава)

Page 141: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriter public void Write()public void Write() {{ lock( this ) lock( this ) {{ while( mReaders != 0 )while( mReaders != 0 ) Monitor.Wait( this );Monitor.Wait( this ); mIsWriting = true;mIsWriting = true; }}

//...WRITING TAKES PLACE HERE...//...WRITING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mIsWriting = false;mIsWriting = false; Monitor.PulseAll( this );Monitor.PulseAll( this ); }} }}}}

Page 142: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriter public void Write()public void Write() {{ lock( this ) lock( this ) {{ while( mReaders != 0 )while( mReaders != 0 ) Monitor.Wait( this );Monitor.Wait( this ); mIsWriting = true;mIsWriting = true; }}

//...WRITING TAKES PLACE HERE...//...WRITING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mIsWriting = false;mIsWriting = false; Monitor.PulseAll( this );Monitor.PulseAll( this ); }} }}}}

Page 143: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriter public void Write()public void Write() {{ lock( this ) lock( this ) {{ while( mReaders != 0 )while( mReaders != 0 ) Monitor.Wait( this );Monitor.Wait( this ); mIsWriting = true;mIsWriting = true; }}

//...WRITING TAKES PLACE HERE...//...WRITING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mIsWriting = false;mIsWriting = false; Monitor.PulseAll( this );Monitor.PulseAll( this ); }} }}}}

Page 144: Многонишково програмиране и синхронизация

CustomReaderWriterCustomReaderWriter public void Write()public void Write() {{ lock( this ) lock( this ) {{ while( mReaders != 0 )while( mReaders != 0 ) Monitor.Wait( this );Monitor.Wait( this ); mIsWriting = true;mIsWriting = true; }}

//...WRITING TAKES PLACE HERE...//...WRITING TAKES PLACE HERE...

lock( this ) lock( this ) {{ mIsWriting = false;mIsWriting = false; Monitor.PulseAll( this );Monitor.PulseAll( this ); }} }}}}

Page 145: Многонишково програмиране и синхронизация

Демонстрация #1Демонстрация #177 CustomReaderWriterCustomReaderWriter

Page 146: Многонишково програмиране и синхронизация

Synchronized WrappersSynchronized Wrappers По подразбиране стандартните колекцииПо подразбиране стандартните колекции

((ArrayListArrayList, , QueueQueue, , StackStack) не са thread safe) не са thread safe HashtableHashtable е thread safe (1 писач, N четеца) е thread safe (1 писач, N четеца) Synchronized Wrapper е синхронизирана Synchronized Wrapper е синхронизирана

обвивка около колекциятаобвивка около колекцията Връща синхронизирана версия на колекциятаВръща синхронизирана версия на колекцията

При При HashtableHashtable – threadsafe (N писача, N четеца) – threadsafe (N писача, N четеца)

Свойството Свойството ICollection.SyncRootICollection.SyncRoot

Stack safeStack = Stack.Synchronized(stack);Stack safeStack = Stack.Synchronized(stack);

locklock (bitArray.SyncRoot)(bitArray.SyncRoot){ { //// Perform thread unsafe operations here Perform thread unsafe operations here } }

Page 147: Многонишково програмиране и синхронизация

Нишки – препоръчвани практикиНишки – препоръчвани практики Избягвайте нуждата от синхронизацияИзбягвайте нуждата от синхронизация,, когато когато

е възможное възможно Използвайте Използвайте Interlocked Interlocked вместо вместо

синхронизациясинхронизация,, където е възможно където е възможно Пазете се от Пазете се от deadlocksdeadlocks Избягвайте Избягвайте lock(..){}lock(..){}, , ако е възможноако е възможно Правете критичните секции възможно най-Правете критичните секции възможно най-

кратки (за да намалите изчакването)кратки (за да намалите изчакването) Член-променливите не е нужно да са Член-променливите не е нужно да са thread thread

safesafe, ако не се достъпват от други нишки, ако не се достъпват от други нишки Статичните членове е нужно да са Статичните членове е нужно да са thread safethread safe Използвайте статични данни само за четене Използвайте статични данни само за четене

((read-only)read-only)

Page 148: Многонишково програмиране и синхронизация

Асинхронни извиквания – Асинхронни извиквания – съдържаниесъдържание

МногозадачностМногозадачност НишкиНишки СинхронизацияСинхронизация Асинхронни извикванияАсинхронни извиквания

Асинхронни извиквания на методиАсинхронни извиквания на методи Къде се поддържа?Къде се поддържа? Асинхронно извикване чрез делегатАсинхронно извикване чрез делегат Design Pattern за асинхр. извикванияDesign Pattern за асинхр. извиквания Интерфейсът Интерфейсът IAsyncResultIAsyncResult Резултат от асинхронен методРезултат от асинхронен метод

Page 149: Многонишково програмиране и синхронизация

Асинхронни извиквания на методиАсинхронни извиквания на методи По подразбиране един метод се По подразбиране един метод се

дефинира като синхронен дефинира като синхронен ((synchronous)synchronous)

Синхронно извикванеСинхронно извикване на метод на метод (synchronous method call)(synchronous method call) Изчаква се неговото приключване и след това Изчаква се неговото приключване и след това

се преминава към следващия операторсе преминава към следващия оператор

Асинхронно извикване на метод Асинхронно извикване на метод ((asynchronous method call)asynchronous method call) Без да се чака приключването на метода, се Без да се чака приключването на метода, се

минава на следващия операторминава на следващия оператор

Механизмът на асинхронното Механизмът на асинхронното извикване използва нишки (извикване използва нишки (ThreadPoolThreadPool))

Page 150: Многонишково програмиране и синхронизация

Къде се поддържа?Къде се поддържа? Вход/изход: File IO, Stream IO, Socket IOВход/изход: File IO, Stream IO, Socket IO Мрежови класове: HTTP, TCPМрежови класове: HTTP, TCP Remoting канали (HTTP, TCP) и прокситаRemoting канали (HTTP, TCP) и проксита ASP.NET XML Web-услугиASP.NET XML Web-услуги ASP.NET Web-приложенияASP.NET Web-приложения При работа с MSMQ (При работа с MSMQ (Microsoft Message Microsoft Message

Queue)Queue) Асинхронни делегатиАсинхронни делегати Потребителски класове, дефиниращи Потребителски класове, дефиниращи

асинхронен интерфейс за извикванеасинхронен интерфейс за извикване

Page 151: Многонишково програмиране и синхронизация

Асинхронно извикване чрез делегатАсинхронно извикване чрез делегат

Делегатите предоставят Делегатите предоставят функционалност за асинхронно функционалност за асинхронно извикване на синхронен методизвикване на синхронен метод Автоматично се генерират Автоматично се генерират

BeginInvoke()BeginInvoke() и и EndInvoke()EndInvoke() с с правилния брой параметриправилния брой параметри

Генерирането става при създаването на Генерирането става при създаването на делегат със съответната сигнатураделегат със съответната сигнатура

Добавя се функционалност без да се Добавя се функционалност без да се изисква нито ред допълнителен кодизисква нито ред допълнителен код

Page 152: Многонишково програмиране и синхронизация

Асинхронно извикване чрез делегатАсинхронно извикване чрез делегат

using System;using System;using System.Threading;using System.Threading;

class AsyncCallclass AsyncCall{{ public delegate int MyDelegate(int a, int b);public delegate int MyDelegate(int a, int b);

public int Sum(int a, int b)public int Sum(int a, int b) {{ Thread.Sleep(3000);Thread.Sleep(3000); return a+b;return a+b; }}

static void Main(string[] args)static void Main(string[] args) {{ MyDelegate asyncCall = new MyDelegate(newMyDelegate asyncCall = new MyDelegate(new AsyncCall().Sum);AsyncCall().Sum); Console.WriteLine("Console.WriteLine("SStarting method async.");tarting method async.");

Page 153: Многонишково програмиране и синхронизация

Асинхронно извикване чрез делегатАсинхронно извикване чрез делегат

IAsyncResult status =IAsyncResult status = asyncCall.asyncCall.BeginInvokeBeginInvoke(5, 6, null, null);(5, 6, null, null); Console.WriteLine("Async method is working");Console.WriteLine("Async method is working");

Console.WriteLine("Calling EndInvoke()");Console.WriteLine("Calling EndInvoke()"); int result = asyncCall.int result = asyncCall.EndInvokeEndInvoke(status);(status); Console.WriteLine("EndInvoke() returned");Console.WriteLine("EndInvoke() returned"); Console.WriteLine("Result={0}", result);Console.WriteLine("Result={0}", result); }}}}

//// РезултатРезултат::Starting method asynchronouslyStarting method asynchronouslyAsynchronous method is working nowAsynchronous method is working nowCalling EndInvoke() Calling EndInvoke() //// тук има пауза, заради Sleepтук има пауза, заради Sleep()()EndInvoke() returnedEndInvoke() returnedResult=11Result=11

Page 154: Многонишково програмиране и синхронизация

Демонстрация #18Демонстрация #18 Асинхронно извикване чрез делегатАсинхронно извикване чрез делегат

Page 155: Многонишково програмиране и синхронизация

Design Pattern Design Pattern зазаасинхронно програмиранеасинхронно програмиране

Случаи, в които се налага изричното Случаи, в които се налага изричното имплементиране на асинхронно имплементиране на асинхронно извикване на методизвикване на метод Ако изричното имплементиране е по-Ако изричното имплементиране е по-

бързо от извикване с делегатбързо от извикване с делегат Ако методът трябва да се извиква само Ако методът трябва да се извиква само

асинхронноасинхронно

В такива случаи строго се В такива случаи строго се препоръчва следването на препоръчва следването на design design pattern-a pattern-a

Page 156: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

int Sum(int a, int b);int Sum(int a, int b);

IAsyncResult BeginSum(int a, int b,IAsyncResult BeginSum(int a, int b, AsyncCallback requestCallback,AsyncCallback requestCallback, object stateObject);object stateObject);

int EndSum(IASyncResult ar);int EndSum(IASyncResult ar);

Page 157: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

int int SumSum(int a, int b);(int a, int b);

IAsyncResult IAsyncResult BeginSumBeginSum(int a, int b,(int a, int b, AsyncCallback requestCallback,AsyncCallback requestCallback, object stateObject);object stateObject);

int int EndSumEndSum(IASyncResult ar);(IASyncResult ar);

Page 158: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

int Sum(int Sum(int a, int bint a, int b););

IAsyncResult BeginSum(IAsyncResult BeginSum(int a, int bint a, int b,, AsyncCallback requestCallback,AsyncCallback requestCallback, object stateObject);object stateObject);

int EndSum(IASyncResult ar);int EndSum(IASyncResult ar);

Page 159: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

intint Sum(int a, int b); Sum(int a, int b);

IAsyncResult BeginSum(int a, int b,IAsyncResult BeginSum(int a, int b, AsyncCallback requestCallback,AsyncCallback requestCallback, object stateObject);object stateObject);

intint EndSum(IASyncResult ar); EndSum(IASyncResult ar);

Page 160: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

int Sum(int a, int b);int Sum(int a, int b);

IAsyncResultIAsyncResult BeginSum(int a, int b, BeginSum(int a, int b, AsyncCallback requestCallbackAsyncCallback requestCallback,, object stateObject);object stateObject);

int EndSum(IASyncResult ar);int EndSum(IASyncResult ar);

delegate void AsyncCallback(IASyncResult ar);delegate void AsyncCallback(IASyncResult ar);

Page 161: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

int Sum(int a, int b);int Sum(int a, int b);

IAsyncResult BeginSum(int a, int b,IAsyncResult BeginSum(int a, int b, AsyncCallback requestCallback,AsyncCallback requestCallback, object stateObjectobject stateObject););

int EndSum(IASyncResult ar);int EndSum(IASyncResult ar);

Page 162: Многонишково програмиране и синхронизация

Асинхронно програмиранеАсинхронно програмиране Нека имаме синхронен методНека имаме синхронен метод

Искаме да предоставим асинхронна версияИскаме да предоставим асинхронна версия В .NET Framework асинхронното извикване В .NET Framework асинхронното извикване

се характеризира с използването на се характеризира с използването на методите методите BeginXXXXXBeginXXXXX и и EndXXXXXEndXXXXX, където , където XXXXXXXXXX е синхронната версия на метода е синхронната версия на метода

Асинхронната версия на метода Асинхронната версия на метода SumSum е: е:

int Sum(int a, int b);int Sum(int a, int b);

IAsyncResult BeginSum(int a, int b,IAsyncResult BeginSum(int a, int b, AsyncCallback requestCallback,AsyncCallback requestCallback, object stateObject);object stateObject);

int EndSum(IASyncResult ar);int EndSum(IASyncResult ar);

Page 163: Многонишково програмиране и синхронизация

IAsyncResultIAsyncResult

Свойството Свойството AsyncStateAsyncState, връща същия обект , връща същия обект подаден като подаден като stateObjectstateObject на на BeginBeginInvoke()Invoke()

Предоставя се, за да се използва от Предоставя се, за да се използва от потребителя, като начин за следене на статусапотребителя, като начин за следене на статуса

Не се използва или променя по какъвто и да Не се използва или променя по какъвто и да било начин от извиквания методбило начин от извиквания метод

public interface IAsyncResultpublic interface IAsyncResult{{ object AsyncState {get;}object AsyncState {get;} WaitHandle AsyncWaitHandle {get;} WaitHandle AsyncWaitHandle {get;} bool CompletedSynchronously {get;}bool CompletedSynchronously {get;} bool IsCompleted {get;}bool IsCompleted {get;}}}

Page 164: Многонишково програмиране и синхронизация

IAsyncResultIAsyncResult

Свойството Свойството AsyncWaitHandleAsyncWaitHandle се използва се използва като параметър на методите като параметър на методите WaitAll()WaitAll(), , WaitOne()WaitOne() или или WaitAny()WaitAny() на класа на класа WaitHandleWaitHandle за изчакване приключването на за изчакване приключването на асинхронния методасинхронния метод

Гореописаният механизъм е един от начините Гореописаният механизъм е един от начините за приключване на асинхронен методза приключване на асинхронен метод

public interface IAsyncResultpublic interface IAsyncResult{{ object AsyncState {get;}object AsyncState {get;} WaitHandle AsyncWaitHandle {get;} WaitHandle AsyncWaitHandle {get;} bool CompletedSynchronously {get;}bool CompletedSynchronously {get;} bool IsCompleted {get;}bool IsCompleted {get;}}}

Page 165: Многонишково програмиране и синхронизация

IAsyncResultIAsyncResult

CompletedSynchronouslyCompletedSynchronously връща връща truetrue ако ако асинхронният метод е приключил работа асинхронният метод е приключил работа преди края на извикването на преди края на извикването на BeginBeginInvokeInvoke метода (т.е. ако работи прекалено бързометода (т.е. ако работи прекалено бързо))

public interface IAsyncResultpublic interface IAsyncResult{{ object AsyncState {get;}object AsyncState {get;} WaitHandle AsyncWaitHandle {get;} WaitHandle AsyncWaitHandle {get;} bool CompletedSynchronously {get;}bool CompletedSynchronously {get;} bool IsCompleted {get;}bool IsCompleted {get;}}}

Page 166: Многонишково програмиране и синхронизация

IAsyncResultIAsyncResult

IsCompletedIsCompleted връща връща truetrue ако ако асинхронният метод е приключил работаасинхронният метод е приключил работа

Може да се използва чрез механизма Може да се използва чрез механизма "polling" – през определено време да се "polling" – през определено време да се проверява истинността на проверява истинността на IsCompletedIsCompleted докато върне докато върне truetrue

public interface IAsyncResultpublic interface IAsyncResult{{ object AsyncState {get;}object AsyncState {get;} WaitHandle AsyncWaitHandle {get;} WaitHandle AsyncWaitHandle {get;} bool CompletedSynchronously {get;}bool CompletedSynchronously {get;} bool IsCompleted {get;}bool IsCompleted {get;}}}

Page 167: Многонишково програмиране и синхронизация

Изчакване на асинхронен методИзчакване на асинхронен метод Има 4 начина да се провери дали е Има 4 начина да се провери дали е

приключил един асинхронен методприключил един асинхронен метод1.1. Механизмът "polling" – проверява се Механизмът "polling" – проверява се

IAsyncResult.IsCompletedIAsyncResult.IsCompleted през през определено времеопределено време

2.2. Чрез Чрез WaitHandle.WaitOne() / WaitHandle.WaitOne() / WaitAll() / WaitAny() WaitAll() / WaitAny() върху върху IAsyncResult.AsyncWaitHandleIAsyncResult.AsyncWaitHandle Може да се задава таймаут, за да не Може да се задава таймаут, за да не

се чака безкрайно дългосе чака безкрайно дълго

3.3. Извикване на Извикване на EndEndInvokeInvoke()(), който , който блокира докато асинхронният метод блокира докато асинхронният метод не свърши работата сине свърши работата си

Page 168: Многонишково програмиране и синхронизация

Изчакване на асинхронен методИзчакване на асинхронен метод Има 4 начина да се провери дали е Има 4 начина да се провери дали е

приключил един асинхронен методприключил един асинхронен метод

4.4. Да се подаде callback метод на Да се подаде callback метод на BeginBeginInvokeInvoke()() чрез делегата чрез делегата AsyncCallbackAsyncCallback

Подаденият метод се извиква, когато Подаденият метод се извиква, когато асинхронният метод приключи работаасинхронният метод приключи работа

От него може да се извика От него може да се извика EndEndInvokeInvoke()() за да се извлече резултатаза да се извлече резултата

delegate void AsyncCallback(IASyncResultdelegate void AsyncCallback(IASyncResult ar)ar)

Page 169: Многонишково програмиране и синхронизация

Демонстрация #19Демонстрация #19 4 начина да изчакаме приключването 4 начина да изчакаме приключването

на асинхронно извикванена асинхронно извикване

Page 170: Многонишково програмиране и синхронизация

Многонишково Многонишково програмиране и програмиране и синхронизациясинхронизация

Въпроси?Въпроси?

Page 171: Многонишково програмиране и синхронизация

ЗадачиЗадачи1.1. Напишете програма, която стартира Напишете програма, която стартира

предварително зададен брой нишки (константа). предварително зададен брой нишки (константа). Всяка нишка изписва “Всяка нишка изписва “Thread X startedThread X started”, спи ”, спи ((Thread.Sleep()Thread.Sleep()) случаен брой милисекунди и ) случаен брой милисекунди и изписва “изписва “Thread X stoppedThread X stopped”. ”. XX трябва да се трябва да се задава в конструктора на класа, който съдържа задава в конструктора на класа, който съдържа метода, използван в метода, използван в ThreadStartThreadStart делегата. делегата.

2.2. Да се промени програмата, така че името на Да се промени програмата, така че името на нишката да се задава от главната нишка и да се нишката да се задава от главната нишка и да се взима след това с взима след това с Thread.CurrentThread.NameThread.CurrentThread.Name..

3.3. Променете горната програма, така че след като Променете горната програма, така че след като стартира всичките нишки, да изписва “стартира всичките нишки, да изписва “Main Main Thread ExitsThread Exits”. Стартирайте я и наблюдавайте ”. Стартирайте я и наблюдавайте резултата. Пазете в масив референция към всяка резултата. Пазете в масив референция към всяка стартирана нишка. Добавете изчакване на всички стартирана нишка. Добавете изчакване на всички стартирани нишки с стартирани нишки с Thread.Join()Thread.Join()..

Page 172: Многонишково програмиране и синхронизация

ЗадачиЗадачи4.4. Напишете Windows Forms приложение, което Напишете Windows Forms приложение, което

стартира едновременно 10 нишки и от всяка от стартира едновременно 10 нишки и от всяка от тях в безкраен цикъл добавя по една буква към тях в безкраен цикъл добавя по една буква към текста, съдържащ се в дадена текста, съдържащ се в дадена TextBoxTextBox контрола. контрола. Наслаждавайте се на забележителния начин по Наслаждавайте се на забележителния начин по който приложението "зависва". Обяснете защо се който приложението "зависва". Обяснете защо се получава този ефект? Обещавате ли никога да не получава този ефект? Обещавате ли никога да не правите подобна глупост?правите подобна глупост?

5.5. Защо при конзолни приложения може много Защо при конзолни приложения може много нишки да пишат по конзолата едновременно?нишки да пишат по конзолата едновременно?

6.6. Преработете предходното приложение, като се Преработете предходното приложение, като се съобразите с препоръката, че потребителският съобразите с препоръката, че потребителският интерфейс на Windows Forms приложенията интерфейс на Windows Forms приложенията трябва да се обновява само и единствено от трябва да се обновява само и единствено от главната им нишка. Използвайте метода главната им нишка. Използвайте метода Form.Invoke()Form.Invoke(), както е показано в примерите., както е показано в примерите.

Page 173: Многонишково програмиране и синхронизация

ЗадачиЗадачи7.7. Напишете Напишете Windows Forms Windows Forms приложение, което приложение, което

стартира нишка при натискане на бутон. Нишката стартира нишка при натискане на бутон. Нишката итерира числата от 1 до 1000 и ги изписва в итерира числата от 1 до 1000 и ги изписва в текстово поле през 200 текстово поле през 200 ms ms (използвайте (използвайте ThreadThread..SleepSleep()()). ). Сложете 2 бутона – единият да Сложете 2 бутона – единият да извиква извиква SuspendSuspend()() за нишката, другият за нишката, другият – – ResumeResume()(). . Тествайте приложението.Тествайте приложението. Замръзва ли Замръзва ли потребителският интерфейс докато работи потребителският интерфейс докато работи нишката? Погрижихте ли се достъпът до нишката? Погрижихте ли се достъпът до потребителския интерфейс да става само през потребителския интерфейс да става само през главната нишка на приложението?главната нишка на приложението?

8.8. Добавете към горната програма още една нишка, Добавете към горната програма още една нишка, която през 100 ms да изписва състоянието на която през 100 ms да изписва състоянието на другата нишка в другата нишка в StatusBarStatusBar контрола. контрола.

9.9. Направете нишките на приложението Направете нишките на приложението background. background. Какво става ако не са такива?Какво става ако не са такива?

Page 174: Многонишково програмиране и синхронизация

ЗадачиЗадачи10.10. Добавете към предната програма бутони Добавете към предната програма бутони

""InterruptInterrupt"" ии " "AbortAbort", които извикват ", които извикват InterruptInterrupt()() и и AbortAbort()() на нишката, която печата числата. на нишката, която печата числата. Тествайте приложението.Тествайте приложението.

11.11. Напишете програма, която стартира 100 нишки. Напишете програма, която стартира 100 нишки. Всяка итерира 3 вложени цикъла от 1 до 1 000 Всяка итерира 3 вложени цикъла от 1 до 1 000 000, като пресмята Sqrt(i+j+k), където i, j, k са 000, като пресмята Sqrt(i+j+k), където i, j, k са водещите променливи в трите вложени цикъла. водещите променливи в трите вложени цикъла. Циклите са за симулиране на работа. Нагласете Циклите са за симулиране на работа. Нагласете циклите така, че да не отнемат нито твърде много циклите така, че да не отнемат нито твърде много нито твърде малко време. Изписвайте “Thread X нито твърде малко време. Изписвайте “Thread X Started” и “Thread X Stopped” съответно преди и Started” и “Thread X Stopped” съответно преди и след като започне работа. Пуснете програмата. след като започне работа. Пуснете програмата. Сменяйте приоритетите на някои от нишките и Сменяйте приоритетите на някои от нишките и наблюдавайте разликите във времето за наблюдавайте разликите във времето за изпълнение на нишките с различни приоритети.изпълнение на нишките с различни приоритети.

Page 175: Многонишково програмиране и синхронизация

ЗадачиЗадачи12.12. Напишете Напишете Windows Forms Windows Forms приложение, което приложение, което

търси текст във всички файлове от дадена търси текст във всички файлове от дадена директория (подобно на търсенето от директория (подобно на търсенето от Windows Windows Explorer). Explorer). Използвайте нишки. Реализирайте по Използвайте нишки. Реализирайте по правилен начин прекратяване на търсенето.правилен начин прекратяване на търсенето.

13.13. Напишете програма, която стартира 2 нишки, Напишете програма, която стартира 2 нишки, всяка от нишките заделя NamedSlot с уникално всяка от нишките заделя NamedSlot с уникално име (използвайки Thread Local Storage) и се име (използвайки Thread Local Storage) и се опитайте да достъпите от всяка от нишките опитайте да достъпите от всяка от нишките данните на другата нишка. Какво се случва?данните на другата нишка. Какво се случва?

14.14. Напишете програма, в която има клас с член-Напишете програма, в която има клас с член-променлива (целочислена), отбелязана с променлива (целочислена), отбелязана с атрибута атрибута [ThreadStatic][ThreadStatic]. Напишете метод, . Напишете метод, който променя стойността й и я отпечатва на който променя стойността й и я отпечатва на екрана. Пуснете няколко нишки с този метод. екрана. Пуснете няколко нишки с този метод. Наблюдавайте резултата. Защо се получава така?Наблюдавайте резултата. Защо се получава така?

Page 176: Многонишково програмиране и синхронизация

ЗадачиЗадачи15.15. ((Race conditionRace condition) ) Напишете клас, който има Напишете клас, който има

статична член-променлива (целочислена). статична член-променлива (целочислена). Напишете метод, който прави локално копие на Напишете метод, който прави локално копие на тази променлива, спи 100тази променлива, спи 100msms., увеличава ., увеличава стойносттастойността на променливата, и я записва на на променливата, и я записва на мястото на статичната член-променлива. Пуснете мястото на статичната член-променлива. Пуснете 100 нишки с този метод. Накрая отпечатайте 100 нишки с този метод. Накрая отпечатайте резултата (изчакайте всичките нишки да резултата (изчакайте всичките нишки да приключат) от главната нишка. Верен ли е?приключат) от главната нишка. Верен ли е?

16.16. ((DeadlockDeadlock) ) Напишете клас, който има два обекта – Напишете клас, който има два обекта – А и В, и два метода. Метод 1 заключва ресурс А А и В, и два метода. Метод 1 заключва ресурс А ((MonitorMonitor..EnterEnter((АА)))) и спи 2000 и спи 2000msms. . След това След това чака за ресурс В чака за ресурс В ((MonitorMonitor..EnterEnter((BB)))). Метод 2 . Метод 2 спи 1000спи 1000msms, , заключва ресурс В, и се опитва да заключва ресурс В, и се опитва да заключи ресурс А. Какво се случва?заключи ресурс А. Какво се случва?

Page 177: Многонишково програмиране и синхронизация

ЗадачиЗадачи17.17. Напишете програма, която има целочислена член-Напишете програма, която има целочислена член-

променлива (брояч). Добавете метод, който променлива (брояч). Добавете метод, който увеличава тази брояч с 1. Изписвайте на екрана увеличава тази брояч с 1. Изписвайте на екрана текст преди и след увеличаването му. Пуснете текст преди и след увеличаването му. Пуснете 100 нишки с този метод. Има ли нещо нередно 100 нишки с този метод. Има ли нещо нередно при работата с брояча?при работата с брояча?

18.18. Синхронизирайте достъпът до брояча с Синхронизирайте достъпът до брояча с locklock..

19.19. Синхронизирайте достъпа до променливата от Синхронизирайте достъпа до променливата от предната задача с предната задача с Monitor.Enter()Monitor.Enter() / / Exit()Exit()..

20.20. Синхронизирайте достъпа до променливата от Синхронизирайте достъпа до променливата от предната задача чрез предната задача чрез ContextBoundObjectContextBoundObject и и [SynchronizationAttribute][SynchronizationAttribute]..

21.21. Синхронизирайте достъпа до променливата от Синхронизирайте достъпа до променливата от предната задача с предната задача с [MethodImplAttribute [MethodImplAttribute (MethodImplOptions.Synchronized)] (MethodImplOptions.Synchronized)]

Page 178: Многонишково програмиране и синхронизация

ЗадачиЗадачи22.22. Синхронизирайте достъпа до променливата от Синхронизирайте достъпа до променливата от

предната задача с предната задача с MutexMutex..

23.23. Синхронизирайте достъпа до променливата от Синхронизирайте достъпа до променливата от предната задача чрез класа предната задача чрез класа InterlockedInterlocked..

24.24. Модифицирайте Модифицирайте Demo-13-Mutex-ExampleDemo-13-Mutex-Example така, че така, че едновременно да работят по най-много 2, а не едновременно да работят по най-много 2, а не най-много 1 нишка. най-много 1 нишка. Подсказка: добавете Подсказка: добавете статична член-променлива, която да брои статична член-променлива, която да брои работещите нишки. Ако броят им е 2 работещите нишки. Ако броят им е 2 блокирайте нишката (блокирайте нишката (Mutex.WaitOne()Mutex.WaitOne()). ). Внимавайте колко пъти освобождавате Внимавайте колко пъти освобождавате заключването (заключването (Mutex.ReleaseMutex()Mutex.ReleaseMutex()). ). Променете изписването на екрана, така че да е Променете изписването на екрана, така че да е адекватно на новата ситуация. Използвайте адекватно на новата ситуация. Използвайте locklock при достъпа до статичната променлива.при достъпа до статичната променлива.

Page 179: Многонишково програмиране и синхронизация

ЗадачиЗадачи25.25. Напишете клас, който има метод, извършващ Напишете клас, който има метод, извършващ

времеотнемащи изчисления. Пуснете 10 нишки да времеотнемащи изчисления. Пуснете 10 нишки да изпълняват този метод. Синхронизирайте изпълняват този метод. Синхронизирайте изпълнението на изчисленията, така че само една изпълнението на изчисленията, така че само една нишка да извършва изчисления в даден момент. нишка да извършва изчисления в даден момент. Използвайте Използвайте AutoResetEventAutoResetEvent – всяка нишка като – всяка нишка като се стартира чака (без първата) и след като се стартира чака (без първата) и след като свърши работа сигнализира на следващата.свърши работа сигнализира на следващата.

26.26. Променете програмата от предната задача, така Променете програмата от предната задача, така че стартирането на първата нишка да се че стартирането на първата нишка да се сигнализира от клавиатурата.сигнализира от клавиатурата.

27.27. Променете предната задача така, че всички Променете предната задача така, че всички нишки да се стартират при натискане на нишки да се стартират при натискане на [Enter][Enter]. . Използвайте Използвайте ManualResetEventManualResetEvent вместо вместо AutoResetEventAutoResetEvent. Каква е разликата?. Каква е разликата?

Page 180: Многонишково програмиране и синхронизация

ЗадачиЗадачи28.28. Реализирайте Реализирайте Windows Forms Windows Forms приложение, което приложение, което

показва коя директория от показва коя директория от C:\C:\ колко място заема колко място заема (заедно с всички файлове и поддиректории). (заедно с всички файлове и поддиректории). Потребителският интерфейс трябва да Потребителският интерфейс трябва да представлява дърво, което съответства на представлява дърво, което съответства на дървото на директориите. Всеки елемент в това дървото на директориите. Всеки елемент в това дърво трябва да е име на директория и да показва дърво трябва да е име на директория и да показва в скоби обемът й (в в скоби обемът й (в KB, MB KB, MB или или GB). GB). За да не чакат За да не чакат прекалено дълго потребителите, трябва след прекалено дълго потребителите, трябва след визуализация на всички поддиректории размерите визуализация на всички поддиректории размерите им да се пресмятат във фонов режим (с отделна им да се пресмятат във фонов режим (с отделна нишка). За директориите, за които размерите се нишка). За директориите, за които размерите се пресмятат в момента и не са все още известни, пресмятат в момента и не са все още известни, вместо размер трябва да се показва в скобите вместо размер трябва да се показва в скобите "working""working". Първоначално активна е коренната . Първоначално активна е коренната директориядиректория. . При избиране на друга директория от При избиране на друга директория от дървото трябва да се показват нейните дървото трябва да се показват нейните поддиректории (заедно с размерите им).поддиректории (заедно с размерите им).

Page 181: Многонишково програмиране и синхронизация

ЗадачиЗадачи29.29. Реализирайте програма, която през 5 секунди Реализирайте програма, която през 5 секунди

проверява какъв е размерът на даден файл проверява какъв е размерът на даден файл (името е зададено като константа) и ако нарасне (името е зададено като константа) и ако нарасне над определен праг (примерно 500 КB), отпечатва над определен праг (примерно 500 КB), отпечатва предупредително съобщение. Използвайте предупредително съобщение. Използвайте ThreadPool.RegisterWaitForSingleObject(…)ThreadPool.RegisterWaitForSingleObject(…)..

30.30. Напишете програма, която реализира Напишете програма, която реализира функционалността на функционалността на Demo-17-Demo-17-CustomReaderWriterCustomReaderWriter използвайки класа използвайки класа ReaderWriterLockReaderWriterLock..

31.31. Решете проблема "производител/консуматор" Решете проблема "производител/консуматор" чрез чрез Monitor.Wait()Monitor.Wait() и и Monitor.Pulse()Monitor.Pulse(). . Направете си примерно приложение, с което да Направете си примерно приложение, с което да тествате дали работи правилно.тествате дали работи правилно.

32.32. Напишете програма, която пуска няколко нишки, Напишете програма, която пуска няколко нишки, които четат и пишат в общ стек. Синхронизирайте които четат и пишат в общ стек. Синхронизирайте достъпа да стека чрез достъпа да стека чрез Stack.Synchronized();Stack.Synchronized();

Page 182: Многонишково програмиране и синхронизация

ЗадачиЗадачи33.33. Синхронизирайте достъпа до стека от Синхронизирайте достъпа до стека от

предходната задача като използвате свойството предходната задача като използвате свойството му му SyncRootSyncRoot..

34.34. Реализирайте Windows Forms приложение, което Реализирайте Windows Forms приложение, което може да търси символни низове във всички може да търси символни низове във всички файлове от зададена директория. Приложението файлове от зададена директория. Приложението трябва да поддържа едновременно търсене на трябва да поддържа едновременно търсене на няколко низа в няколко директории. Използвайте няколко низа в няколко директории. Използвайте Thread Pool-а на .NET Framework. При всяка Thread Pool-а на .NET Framework. При всяка заявка за търсене добавяйте в него задача. заявка за търсене добавяйте в него задача. Визуализирайте резултатите в Визуализирайте резултатите в ListBoxListBox контрола. контрола.

35.35. Реализирайте предходната задача, като вместо Реализирайте предходната задача, като вместо Thread Pool Thread Pool използвате асинхронно извикване на използвате асинхронно извикване на метод чрез делегат.метод чрез делегат.

Page 183: Многонишково програмиране и синхронизация

MSDN Training, Programming with the MSDN Training, Programming with the Microsoft .NET Framework (C# .NET) (MOC 2349C), Microsoft .NET Framework (C# .NET) (MOC 2349C), Module 14: Threading and Asynchronous Module 14: Threading and Asynchronous Programming –Programming – http://www.microsoft.com/learning/syllabi/en-us/2349http://www.microsoft.com/learning/syllabi/en-us/2349bfinal.mspxbfinal.mspx

MSDN Library, Using Threads and Threading .NETMSDN Library, Using Threads and Threading .NET – – http://msdn.microsoft.com/library/default.asp?url=/libhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconUsingThreadsrary/en-us/cpguide/html/cpconUsingThreads Threading.aspThreading.asp

MSDN Library, Threads and ThreadingMSDN Library, Threads and Threading – –http://msdn.microsoft.com/library/default.asp?url=/libhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconThreadsThreading.asprary/en-us/cpguide/html/cpconThreadsThreading.asp

MSDN Library, Synchronizing Data for MultithreadingMSDN Library, Synchronizing Data for Multithreadinghttp://msdn.microsoft.com/library/default.asp?url=/libhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconmanagedthreading surary/en-us/cpguide/html/cpconmanagedthreading support.asppport.asp

Използвана литератураИзползвана литература

Page 184: Многонишково програмиране и синхронизация

MSDNMSDN Library Library,, Thread Pooling – Thread Pooling – http://msdn.microsoft.com/library/default.asp?url=/lihttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconthreadpooling.aspbrary/en-us/cpguide/html/cpconthreadpooling.asp

MSDN, Application Domains Overview – MSDN, Application Domains Overview – httphttp://msdn.microsoft.com/library/en-us/cpguide/://msdn.microsoft.com/library/en-us/cpguide/ html/cpconapplicationdomainsoverview.asphtml/cpconapplicationdomainsoverview.asp

MSDN, Visual Studio .NET – Product Overview – MSDN, Visual Studio .NET – Product Overview – http://msdn.microsoft.com/vstudio/productinfo/overhttp://msdn.microsoft.com/vstudio/productinfo/overview/view/

Classical synchronization problemsClassical synchronization problems – – httphttp://nob.cs.ucdavis.edu/classes/ecs150-1999-02/sync-://nob.cs.ucdavis.edu/classes/ecs150-1999-02/sync-problems.htmlproblems.html

Multithreading Part 1: Multitasking and Multithreading Part 1: Multitasking and Multithreading by Manish MehtaMultithreading by Manish Mehta – – http://www.c-sharpcorner.com/Code/2002/April/MtP1http://www.c-sharpcorner.com/Code/2002/April/MtP1MtVsMt.aspMtVsMt.asp

Използвана литератураИзползвана литература

Page 185: Многонишково програмиране и синхронизация

Multithreading Part 2: Understanding the Thread Class Multithreading Part 2: Understanding the Thread Class by Manish Mehta – by Manish Mehta – httphttp://://www.c-sharpcorner.com/Code/www.c-sharpcorner.com/Code/ 2002/April/System.Threading.ThreadMT2.asp2002/April/System.Threading.ThreadMT2.asp

Multithreading Part 3: Thread Synchronization by Multithreading Part 3: Thread Synchronization by Manish Mehta – Manish Mehta – httphttp://://www.c-sharpcorner.com/Code/www.c-sharpcorner.com/Code/ 2002/April/MultithreadingP3.asp2002/April/MultithreadingP3.asp

Multithreading Part 4: The ThreadPool, Timer Class and Multithreading Part 4: The ThreadPool, Timer Class and Asynchronous Programming Discussed by Manish Asynchronous Programming Discussed by Manish Mehta – Mehta – http://http://www.c-sharpcorner.com/Code/2002/www.c-sharpcorner.com/Code/2002/ April/MtP4MtVsMt.aspApril/MtP4MtVsMt.asp

Using asynchronous method calls in C#Using asynchronous method calls in C# by by Shawn Shawn Dillon – Dillon – http://uk.builder.com/programming/http://uk.builder.com/programming/ java/0,39026606,20264369,00.htmjava/0,39026606,20264369,00.htm

Използвана литератураИзползвана литература

Page 186: Многонишково програмиране и синхронизация

Multithreading In C# by Mubbsher – Multithreading In C# by Mubbsher – http://www. codeproject.com/csharp/Multithreading_In_http://www. codeproject.com/csharp/Multithreading_In_C_.aspC_.asp

Multithreading with C# by Raffi Krikorian – Multithreading with C# by Raffi Krikorian – http://www. ondotnet.com/pub/a/dotnet/2001/08/06/csharhttp://www. ondotnet.com/pub/a/dotnet/2001/08/06/csharp.htmlp.html

Multithreading In C# by Arun GGMultithreading In C# by Arun GGhttp://www.csharphelp.com/archives/archive128.htmlhttp://www.csharphelp.com/archives/archive128.html

Използвана литератураИзползвана литература