1 / 81

Programowanie Aplikacji Lokalnych w Środowisku .NET

Programowanie Aplikacji Lokalnych w Środowisku .NET. Synchronizacja Obiekty synchronizacyjne Pula w ątków MS Parallel Computing Initiative Operacje asynchroniczne. Synchronizacja. Nieprzerywalne operacje Ochrona sekcji krytycznej Odmiany semaforów

eudora
Download Presentation

Programowanie Aplikacji Lokalnych w Środowisku .NET

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ProgramowanieAplikacjiLokalnychw Środowisku .NET Synchronizacja Obiektysynchronizacyjne Pula wątków MS Parallel Computing Initiative Operacjeasynchroniczne

  2. Synchronizacja • Nieprzerywalneoperacje • Ochronasekcjikrytycznej • Odmianysemaforów • Inneobiekty o własnościachsemaforów • Innemetodysynchronizacji

  3. Synchronizacja • synchronizacja - szeregowanie w czasieoperacjiwątków Należyunikać! • aktywnegoczekaniajakometodysynchronizacji (SpinLock, SpinWait?) • Uśpieniewątku: Thread.Sleep(TimeSpan) • Najprostszysposóboczekiwanianakoniecwątku - Thread.Join(TimeSpan)

  4. Synchronizacja w trybie użytkownika • Dużomniejkosztownaniżwykorzystanieobiektówjądra • Możliwe jest synchronizowanietylkowątkówtegosamegoprocesu • Funkcjeatomowe: • InterlockedIncrement, • InterlockedDecrement, • InterlockedExchancheAdd, • InterlockedExchanche, (32bit) • InterlockedExchanchePointer, (64bit) • InterlockedCompareExchanche • .NET - class Interlooked • CompareExchange, Decrement, Exchange, Increment

  5. Sekcja krytyczna • Synchronizacja w trybieużytkownika • Możliwe jest synchronizowanietylkowątkówtegosamegoprocesu • Uwagawykonanie „wait” możespowodować – zmianętrybu Typobiektu: CRITICAL_SECTION Operacjenasekcjikrytycznej: • InitializeCriticalSectioninicjalizacjasekcjikrytycznej • DeleteCriticalSectionzwolnieniesekcjikrytycznej • EnterCriticalSectionwejście do sekcjikrytycznej • LeaveCriticalSectionwyjście z sekcjikrytycznej • TryEnterCriticalSectionsprawdzeniesekcjikrytycznej • .NET: Monitor

  6. Sekcjakrytyczna – C# - lock lock (x){ .... } System.Threading.Monitor.Enter(x); try { ... } finally { System.Threading.Monitor.Exit(x); } • Kontekst pozwala identyfikować poszczególne instancje sekcji krytycznej • Abyuzyskaćglobalnykontekstmożnaskorzystać z konstrukcjitypeofnp. lock(typeof(myObject)) synchronizowalnewrapery do zmiennychnp. HashtablemyHT = new Hashtable(); HashtablemySyncHT = Hashtable.Synchronized(myHT);

  7. Dostęp do zmiennych Thread Local Storage LocalDataStoreSlotlds = Thread.GetNamedDataSlot("COOKIE"); Thread.SetData(lds, "abc"); var napis = (string) Thread.GetData(lds); Synchronizowalnewrapery do zmiennychnp. HashtablemyHT = new Hashtable(); HashtablemySyncHT = Hashtable.Synchronized(myHT); lock(mySyncHT.SyncRoot) { foreach (Object item inmySyncHT) { // to do smthg }

  8. Obiekty synchronizacyjne Synchronizacja w trybie jądra jest dużo bardziej kosztowna • Odmiany semaforów • Mutex – semafor binarny • Semaphore – semafo wielowartościowy • Event – zdarzenie • Waitable timer – budzik: NT, 2K, XP • powiadomienie o zmianie w systemie plików • Obiekty, które mają własności semaforów: • proces, wątek - sygnalizowane po zakończeniu • zadanie - sygnalizowane po wyczerpaniu limitu czasu • plik - sygnalizowane gdy nie trwają operacje we/wy • wejściekonsoli - sygnalizowane gdy są jakieś znaki w buf.

  9. Nazwy obiektów synchronizacyjnych • korzystanie z jednego obiektu przez różne procesy • małe i duże litery są rozróżniane • długość nieprzekraczająca _MAX_PATH • znaki dozwolone takie jak dla nazwy pliku (bez \) • obiekty synchronizacyjne dzielą tę samą przestrzeń nazw • przestrzeń nazw dla obiektów synchronizacyjnych jest rozłączna z przestrzenią nazw systemu plików

  10. Obiekt synchronizacyjny • obiektprzyjmującystany • signaled – semaforpodniesiony • not signaled– semaforopuszczony • operacje • zasygnalizowanie (podniesieniesemafora - funkcjededykowanedlatypuobiektu • likwidacjastanuzasygnalizowanego (opuszczeniesemafora) – funkcjewspólnedlawszystkichtypówobiektów

  11. Opuszczanie semafora • opuszczeniepojedynczegosemafora DWORD WaitForSingleObject (HANDLE hObject, DWORD dwMiliseconds) ; INFINITE • opuszczaniezbiorusemaforówDWORD WaitForMultipleObjects(DWORD nCount, CONST HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMiliseconds) • Oczekiwanieprzerywanekomunikatami MsgWaitForMultipleObjects • Oczekiwanieprzerywaneoperacjami I/O WaitForSingleObjectEx((HANDLE hObject, DWORD dwMiliseconds, BOOL bAlertable) ; WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx SignalObjectAndWait(HANDLEhObjectToSignal,HANDLE hObjectToWait, DWORD dwMiliseconds, BOOL bAlertable) ;

  12. Opuszczanie semafora .NET class WaitHandle {public virtual Boolean WaitOne();public static Boolean WaitAll(WaitHandle[]);public static Boolean WaitAny(WaitHandle[]);…public virtual Boolean WaitOne(int, bool);public virtual Boolean WaitOne(TimeSpan, bool);public virtual Boolean SignalAndWait (WaitHandle, WaitHandle) public virtual Boolean SignalAndWait (WaitHandle, WaitHandle, TimeSpan, Boolean);public virtual IntPtrHandle { get; set; }public SafeWaitHandleSafeWaitHandle { get; set; } };

  13. Opuszczanie semafora .NET class ManualResetEvent : WaitHandle; class AutoResetEvent : WaitHandle; class Mutex : WaitHandle; class Semaphore : WaitHandle;

  14. Event • Zdarzenie - obiektdwustanowy, służący do sygnalizowaniazajściawydarzenia • Synchronizacjawątkówdowolnychprocesów • Typyzdarzeń • manual-reset event -podniesieniewznawiawszystkiewątki • automatycznieopuszczane - podniesieniewznawiazawszejedenwątek • Operacjenazdarzeniu • CreateEvent(PSECURITY_ATRIBUTE psa, BOOL bManual, BOOL bInitial, PCSTR pszName) • OpenEvent • SetEvent - podniesienie • ResetEvent - opuszczenie • PulseEvent - podniesienieiopuszczenie - zwalniawszystkieczekającewątki (manual) lubjeden(auto) • .Net: AutoResetEvent, ManualResetEventAutoResetEventSlim, ManualResetEventSlim (.Net 4.5)

  15. Mutex • Semaforbinarny - obiektdwustanowy • Umożliwiasynchronizacjęwątkówdowolnychprocesów • Podniesieniesemaforabinarnegowznawiatylkojedenwątek • Mutex jest własnościąwątku: • wąteknieczekanazajętymjużprzezsiebieMutexie, ale trzebaodpowiedniąliczbęrazywołaćReleaseMutex) • podnieśćMutexamożetylkowątek, który go opuścił (dlainnychwątkówReleaseMutexniedajeefektu) • zakończeniewątkubędącegowłąścicielemmuteksapodnosi ten semafor -> wynikWaitFor... = WAIT_ABANDONED • Operacjenasemaforzebinarnym • CreateMutex (PSECURITY_ATRIBUTE psa, BOOL bInitialOwned, PCSTR pszName) • OpenMutex • ReleaseMutexpodniesienie, opuszczaniesemafora: WaitFor... • .NET:Mutex

  16. Semaphore • Semaforwielowartościowycechujeograniczonaliczbastanów (0 oznaczasemaforopuszczony) • Próbaopuszczeniasemaforzmniejszalicznik o 1 • Podniesieniesemaforazwiększalicznikiwznawiatylewątków, o ilezostałzmniejszonylicznik • Opuszczenieipodniesieniemożebyćwykonaneprzezróżnewątki • operacjenasemaforzewielowartościowym • CreateSemaphore(PSECURITY_ATRIBUTE psa, LONGlInitialCount, LONGlMaximumCount, PCSTR pszName) • OpenSemaphore • ReleaseSemaphorepodniesienie • .NET: Semaphore, SemaphoreSlim(>=.Net 4.5 – zalecany, pracujehybrydowotj. nieuzywa obj. jądrapókinie jest to konieczne)

  17. .NET: ReaderWriterLock(Slim) • Semafordedykowanydlaasymetrycznejsytuacjigdzeistniejemożliwośćwieludostępów vs. dostępwyłączny • operacjenasemaforzewielowartościowym • IsReaderLockHeld, IsWriterLockHeld • WriterSeqNum • AcquireReaderLock, AcquireWriterLock • AnyWritersSince • UpgradeToWriterLock, DowngradeFromWriterLock • ReleaseReaderLock, ReleaseWriterLock • RestoreLock, ReleaseLock.

  18. .NET: Barrier Barrier jest obiektem synchronizacyjnym, który pozwala na zatrzymanie wykonania większej liczby wątków w określonym punkcie dopóki nie zostanie on osiagnięty przez wszystkie wątki Dennis Mac Charlie Gas Station = Barrier Boston

  19. Barrier - Code

  20. .NET: CountdownEvent CountdownEventjest obiektem synchronizacyjnym który pozwala śledzić wykonanie wiekszej liczby zadań i sygnalizować ich zakończenie. JOIN FORK Master Thread Master Thread Parallel Region

  21. CountdownEvent - Code

  22. Powiadomienie o zmianie w systemieplików • powiadomienie jest semaforem, któryzmieniastannapodniesiony w chwiliwystąpieniazmiany w systemieplików • zleceniedokonaniapierwszegopowiadomienia HANDLE FindFirstChangeNotification( LPTSTR lpszPath, // ścieżka BOOL fWatchSubTree, // czyzmianapoddrzewa DWORD fdwFilter) ; // rodzajzmiany • FindNextChangeNotification - zleceniedokonaniakolejnegopowiadomienia • FindCloseChangeNotification - rezygnacja • WaitFor... - oczekiwanienapowiadomienie • .NET: System.IO.FileSystemWatcher

  23. Inne metody synchronizacji • WaitForInputIddle(HANDLE hProcess, DWORD wMillisecinds) • .NET : System.Diagnostics.Process.WaitForInputIdle Czekaażwątekgłównyprzetworzywszystkiekomunikaty (np. emulacjanaciśnięćklawiszy)

  24. O mierzeniuczasu • Sleep(x) • System.Threading.Timer(inny wątek via ThreadPool) • System.Timers.Timer(inny wątek) • Dedykowanedlaokien: • System.Windows.Forms.Timer(WindowsForms) • System.Windows.Threading.DispatcherTimer (WPF) • Waitable timer

  25. Waitable timer - NT/2K/XP • budzik jest obiektemczasu, który jest sygnalizowanypoupływieokreślonegoczasu (jednorazowolubcyklicznie) • typybudzików • jednokrotne, cykliczne • sposóbopuszczania • ręczneopuszczane- podniesieniewznawiawszystkiewątki • synchronizacja - podniesionywznawiatylkojedenwątek • operacjenabudziku • CreateWaitableTimer(PSECURITY_ATRIBUTEpsa, BOOL bInitialOwned, PCSTR pszName) • OpenWaitableTimer • SetWaitableTimer (HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletitionRoutine, PVOID pvArgToCompletitionRoutine, BOOL fResume) • CancelWaitableTimer - zatrzymanie

  26. .NET vs API • Wołaniefunkcjiunmanage – wymagaichzaimportowania: [DllImport("msvcrt.dll")] using System; using System.Runtime.InteropServices; class PlatformInvokeTest { [DllImport("msvcrt.dll")] public static extern intputs(string c); [DllImport("msvcrt.dll")] internal static extern int_flushall(); public static void Main() { puts("Test"); _flushall(); } } MSDN -> Platform Invoke Tutorial

  27. System.Threading.Timer Class Timer { ... public Timer (TimerCallback); public Timer (TimerCallback, Object, TimeSpan, TimeSpan); public Timer.Change (TimeSpan, TimeSpan); ... }; • F.callbacku jest obsługiwanaprzez thread pool

  28. DeadLock object l1 = new object(); object l2 = new object(); new Thread (() => { lock (l1) { Thread.Sleep (1000); lock (l2); // Deadlock } }).Start(); lock (l2) { Thread.Sleep (1000); lock (l1); // Deadlock }

  29. DeadLock - zapobieganie • Zajmowaniezasobów w takiejsamejkolejności • UżycieWaitAll

  30. Leniwainicjalizacja class Foo { Expensive _expensive; public Expensive Expensive { // Lazily instantiate Expensive Get { if (_expensive == null) _expensive = new Expensive(); return _expensive; } } ... } lock

  31. TLS static ThreadLocal<int> _x = new ThreadLocal<int> (() => 3); varlocalRandom = new ThreadLocal<Random>( () => new Random (Guid.NewGuid().GetHashCode()) );

  32. TLS class Test { LocalDataStoreSlot _secSlot = Thread.GetNamedDataSlot ("securityLevel"); intSecurityLevel { get { object data = Thread.GetData (_secSlot); return data == null ? 0 : (int) data; // null == unintl. } set { Thread.SetData (_secSlot, value); } } ... }

  33. Wielozadaniowość w .NET

  34. Wątki Kiedyużywać:Długiezadania, priorytetinnyniż normal, foreground task • new Thread (() => { } ).Start(); • new Thread (() => { } ).Start(startState); Wynik dla: for (int i = 0; i < 10; i++) new Thread (() => Console.Write (i)).Start();

  35. Kosztwątku: • Pamięć: • Obiektjądra (1.2 kB) • Thread environment block (4/8 kB 32/64b) • Stos (trybużytkownika 1MB) • Stos (trybjądra 12/24kB dla 32/64b) • DllMain -> DLL_THREAD_ATTACH/ DLL_THREAD_DETACH • Wniosek: wątkikosztująinienależyichnadużywać

  36. Wątki Wątek CLR == wąteksystemowy(jakdotąd) Start nowegowątku: • new Thread (() => { } ).Start(); • new Thread (() => { } ).Start(startState); Jaki będzie wynik dla: for (int i = 0; i < 10; i++) new Thread (() => Console.Write (i)).Start();

  37. Wątki Wątek CLR == wąteksystemowy(jakdotąd) Start nowegowątku: • new Thread (() => { } ).Start(); • new Thread (() => { } ).Start(startState); Jaki będzie wynik dla: for (int i = 0; i < 10; i++) new Thread (() => Console.Write (i)).Start(); a dla for (inti = 0; i < 10; i++) { int temp = i; new Thread (() => Console.Write (temp)).Start(); }

  38. Wątki Kiedyużywać: • długiezadania, • priorytetinnyniż normal • zadania foreground

  39. Pula wątków - .NET • Obiektsystemowy: ThreadPool • Uruchamianie: ThreadPool.QueueUserWorkItem (notUsed => Console.WriteLine ("Msg from pool")); • Kiedyużywać: • krótkiezadania (<250ms, idealnie<100ms), • priorytet normal, • zadania background • Używaneprzez : WCF, Remoting, ASP.NET, and ASMX Web Services, System.Timers.TimeriSystem.Threading.Timer, BackgroundWorkerasynchr. delegaty

  40. Wątki, pula Problemy: • Odbieraniewartości z wątku • Odebranieiprzekazanieew. wyjątków • Czekanienawątek (synchronizacja) blokujeinnywątek Czekanie: new Thread (() => Console.Write (“test”)).Start().Join(); lub varendOfWork = new CountdownEvent(10); for (vari=1; i<=10; i++) new Thread (() =>endOfWork.signal()).Start(); endOfWork.wait();

  41. Czekanieinaczej var threads = new list<Thread>(); for (vari=1; i<=10; i++) { var t = new Thread (() =>endOfWork.signal()); t.Start(); threads.Add(); } WaitHandle.WaitAny(threads, true); // false ?

  42. Parallel Extensions .Net 4.x • .NET Library • Mogą być wykorzystywane we wszystkich językach na platformie .NET • Obejmuje 3 różne elementy • Parallel LINQ (PLINQ) • Task Parallel Library (TPL) • Coordination Data Structures (CDS)

  43. Od watków do zadań (1)

  44. Od watków do zadań (2)

  45. Task Scheduler Local Queue Local Queue Global Queue Worker Thread 1 Program Thread Worker Thread p Task 1 Task 3 Task 4 Task 5 Task 2

  46. Task - .NET 4.X • Zebyzadaniemiałosens – jegodługosc > 200-300 cykli • Domyslnie scheduler używaglobalnejkolejki (można to zmienić) • Abyzapewnićnp. priorytetylubniekorzystanie z .Netpuliwątkówkoniczne jest zaimplementowaniewłasnegoschedulera.

  47. Task - .NET 4.X • Uruchamianie: Task task = Task.Run (() => Console.WriteLine (“Task")).Start(); Zadaniasądomyślnierealizowaneprzezpulę • Długiezadania (nieblokująpuli): Task task = Task.Factory.StartNew (() => …, TaskCreationOptions.LongRunning); • Oczekiwanienazakończeniezadania task.Wait(); lub Task<int> task = Task.Run (() => { return 3; }); Int ret = task.Result;

  48. Task vs. wyjątki • Nieobsłużonewyjątkisąprzechowywane (iwyrzucane) • w momencieodczytuzwrotu • lubwykonania Wait nazadaniu • W 4.0 byływyrzucaneprzyfinalizatorze (crash aplikacji) • CLR opakowujewyjątki wAggregateException Task task = Task.Run ( () => { throw new ApplicationException(“Problem”); }); try { task.Wait(); } catch (AggregateExceptionaex) { Console.WriteLine (aex.InnerException.ToString() ); } • Stan zadaniamożnasprawdzićprzezIsFaultediIsCanceled • Sam wyjątek jest dostępnyprzezwłaściwośćException

  49. Task - kontynuacje varbasicTask=new Task<int> (()=> {return 5;} ); basicTask.ContinueWith (antecedent => { int result = antecedent.Result; Console.WriteLine (result); // Writes 123 }); basicTask.Start(); • Zwyklekolejnezadaniawykonuje ten samwątek (dlaguizawsze) • jeslichcemymiećpewność: ContinueWith (antecedent =>{…}, TaskContinuationOptions.ExecuteSynchronously); • Możnazdefiniowaćkilkanastępców. Domyślniezostanąuruchomionewszystkienaraz. ExecuteSynchronously je szerguje. • Inneopcje: NotOnCanceled, OnlyOnCanceled, LazyCancellation, LongRunning, NotOnFaulted,

  50. Task - zagnieżdzony var parent = Task.Factory.StartNew(() => { Console.WriteLine("Outer task executing."); var child = Task.Factory.StartNew(() => { Console.WriteLine("Nested task starting."); Thread.SpinWait(500000); Console.WriteLine("Nested task completing."); }); }); parent.Wait();

More Related