Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

V 1.0 OE-NIK HP 1 Haladó Programozás System.Threading.Tasks.Task.

Hasonló előadás


Az előadások a következő témára: "V 1.0 OE-NIK HP 1 Haladó Programozás System.Threading.Tasks.Task."— Előadás másolata:

1 V 1.0 OE-NIK HP 1 Haladó Programozás System.Threading.Tasks.Task

2 V 1.0 Egy szál / több szál? A többszálúság biztosítja a program/OS válaszkészségét, de... A szál DRÁGA (megj: OS-függő, Windowsra vonatkozik) Memóriafoglalás szálanként: –Stack, szálkontextus (stb.) Szálak használatából adódó processzoridő-veszteség: –Időosztás menedzselésével elvesztett idő Ideális: annyi szál/program, ahány mag –Szálváltáskor a futási környezet változásából adódó cache miss-ek Újabb szálváltáskor újabb cache miss-ek... –Szál létrehozásakor és megszüntetésekor a programban betöltött natív.dll-ekben Dll_Main(DLL_THREAD_ATTACH), Dll_Main(DLL_THREAD_DETACH) hívások történnek Megj: powerpnt.exe 147 dll!!!!... VS 2012: 183 dll... Szál overhead < process overhead OE-NIK HP 2

3 V 1.0 Task A szálak drágák, létrehozásuk különösen erőforrásigényes Régebbi megoldás: ThreadPool –Előre létrehozott szálakat tartalmaz, ezekre oszthatók ki feladatok –A használattól függően menedzseli a szálak számát Hátrányok: –A szálak kívülről nem elérhetők (kész van-e?) –Visszatérési érték adását nem támogatja A Taskokat ún. TaskScheduler osztja ki (többnyire) a ThreadPool száljaira, intelligens módon –Hosszú műveleteknél ThreadPoolon kívüli szál létrehozására is képes OE-NIK HP 3 static void Main(string[] args) { ThreadPool.QueueUserWorkItem(ComputeBoundOp, 5); } private static void ComputeBoundOp(object state) { /* Long running operation */ }

4 V 1.0 Hagyományos szál vs. Task Használjunk hagyományos szálakat, ha: –A szálnak a normálistól eltérő prioritással kell futnia – a ThreadPool-on minden szál normál prioritással fut –Előtérszálra van szükség – minden ThreadPool szál háttérszál –A szál extrém hosszú műveletet végez (pl. az alkalmazás teljes élettartama alatt futnia kell) –Abort()-ra lehet szükség Minden más esetben Task ajánlott OE-NIK HP 4

5 V 1.0 Task indítása Nem garantált a külön szál – TaskScheduler dönti el –Taskok indítása paraméter nélkül, paraméterrel: –A new Task Action-t vagy Action -et vár el, a Task.Run csak Action-t! – –Taskok indítása visszatérési értékkel rendelkező művelet esetén: –Az összes fenti módszerrel lehet visszatérési értékkel rendelkező Taskot indítani –A Result tulajdonság megvárja a művelet végét (blokkol), ezért érdemes nem azonnal a Start után hívni (vagy lásd később) 5 new Task(LongOperation).Start(); new Task(LongOperationWithParam, 15).Start(); Task t = Task.Run(() => LongOperation()); //.NET 4.5 Task t = Task.Run(() => LongOperationWithParam(15)); //.NET 4.5 Task t = new TaskFactory().StartNew(LongOperation); Task task = new Task (LongOperationWithReturnValue); task.Start(); // Func ! //... más műveletek... int result = task.Result; Console.WriteLine(result);

6 V 1.0 Várakozás Taskra Bármilyen esetben, amikor a Task műveletére várni kell (pl. eredményt képez, tömböt feltölt, beállítást végez, fájlt ment…) –Hátrány: ezek a hívások mind blokkolnak –Megoldás: Continuation-ök OE-NIK HP 6 task.Wait(); //várakozás, míg kész (blokkol) Task.WaitAll(taskArray); //várakozás, míg mind kész (blokkol) Task.WaitAny(taskArray); //várakozás, míg legalább az egyik kész (blokkol) //vagy Task.WaitAll(task1, task2, task3); //mint fent Task.WaitAny(task1, task2, task3); //mint fent

7 V 1.0 Continuation-ök Az eredeti Task lefutása után egy új Task indul majd a megadott művelettel (a t az előző, befejeződött Taskra való referencia) –Feltételes indítás: OE-NIK HP 7 Task continuedTask = new Task (LongOperationWithReturnValue); //nem blokkol, mint a Wait: continuedTask.ContinueWith(t => Console.WriteLine("The result was: " + t.Result)); //csak ha hiba nélkül futott az eredeti Task: continuedTask.ContinueWith(t => Console.WriteLine("The result was: " + t.Result), TaskContinuationOptions.OnlyOnRanToCompletion); //csak ha cancelezték az eredeti Taskot: continuedTask.ContinueWith(t => Console.WriteLine("The task was canceled!"), TaskContinuationOptions.OnlyOnCanceled); //csak ha hibára futott az eredeti Task: continuedTask.ContinueWith(t => Console.WriteLine("The task threw " + "an exception: " + t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted);

8 V 1.0 Task hibakezelés Ha egy Taskban hiba történik, az Exception lenyelődik, és a Wait() vagy Result hívásakor dobódik el egy gyűjteményes Exception (AggregateException) formájában –Egy Tasknak lehet több gyermek taskja is: több Exception is elképzelhető –Az AggregateException példányban InnerExceptions gyűjteményben vannak a konkrét kivételpéldányok OE-NIK HP 8 Task taskWithException = new Task (LongOperationWithReturnValueAndException); taskWithException.Start(); try { result = taskWithException.Result; } catch (AggregateException ex) { foreach (Exception innerException in ex.InnerExceptions) Console.WriteLine(ex.Message); }

9 V 1.0 Task hibakezelés Másik megoldás feltételes continuation segítségével: OE-NIK HP 9 Task taskWithContinuation = new Task(LongOperationWithException); taskWithContinuation.ContinueWith((t) => { Console.WriteLine("THERE WAS AN EXCEPTION: {0}", t.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted); taskWithContinuation.Start();

10 V 1.0 Task leállítása (canceling) A Task-ban végzett műveletben kell kezelni a leállítás lehetőségét Ún. CancellationTokenen keresztül történik a Task értesítése Használható ellenőrzési módok: –cancellationToken.IsCancellationRequested: bool tulajdonság. Ha igaz, ki kell lépni a függvényből –cancellationToken.ThrowIfCancellationRequested(): Exception keletkezik, ha leállítás volt kérelmezve (ezzel kilép a függvényből) –Előny: az Exception egyértelműen mutatja, hogy a leállás nem a művelet vége miatt történt OE-NIK HP 10 static void CancellableLongOperation(CancellationToken cancellationToken) { for (int i = 0; i < 100; i++) { cancellationToken.ThrowIfCancellationRequested(); Thread.Sleep(100); }

11 V 1.0 Task leállítása (canceling) ex.Handle lekezeltnek nyilvánítja az AggregateExceptionben található kivételeket, ha azok megfelelnek a megadott feltételnek Amennyiben maradt még kezeletlen kivétel, új kivételdobás történik Ha nem maradt kezeletlen kivétel, nincs dobás, lefut az utolsó sor is CancellationToken.None adható át, ha le akarjuk tiltani a leállítást OE-NIK HP 11 CancellationTokenSource source = new CancellationTokenSource(); Task taskWithCancel = Task.Run(() => CancellableLongOperation(source.Token), source.Token); source.Cancel(); try { taskWithCancel.Wait(); } catch (AggregateException ex) { ex.Handle(e => e is OperationCanceledException); Console.WriteLine("A műveletet leállították."); }

12 V 1.0 GUI-elem kezelése Windows-os grafikusfelület-elemekhez általában nem lehet hozzányúlni, csak a létrehozó szálról (GUI szál) –Még közvetve sem –WPF, Windows Forms is! –Van kevés kivétel (bizonyos függvények, adatkötésnél a PropertyChanged) Általános megoldás: Invoke –Függvény végrehajtatása a GUI szállal OE-NIK HP 12 Dispatcher.Invoke(() => { label.Content =...; listBox.Items.Add(...); });

13 V 1.0 GUI-elem kezelése Rövidebb módszer, ha a Task eredményét kiíró műveletet is külön Taskként indítjuk, megadott taskütemező (TaskScheduler) segítségével Beépített taskütemezők: –Thread Pool Task Scheduler: a ThreadPool-on indítja a taskokat (alapértelmezett) –Synchronization Context Task Scheduler: a felhasználói felület szálján indítja a taskokat – ezzel kell indítani, ha GUI-elemet akarunk kezelni Referencia „megszerzése”: a GUI szálján TaskScheduler.FromCurrentSynchronizationContext() OE-NIK HP 13 Task taskWithReturnValue = Task.Run(() => { Thread.Sleep(1000); return 6; }); taskWithReturnValue.ContinueWith( t => textBox1.Text = "Result: " + t.Result, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());

14 V 1.0 Feladat OE-NIK HP 14

15 V 1.0 Forrás: Jeffrey Richter: CLR via C# 4th edition OE-NIK HP 15


Letölteni ppt "V 1.0 OE-NIK HP 1 Haladó Programozás System.Threading.Tasks.Task."

Hasonló előadás


Google Hirdetések