La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Async Programming EXT402 Raffaele Rialdi Visual Developer Security MVP MVP Profile

Presentazioni simili


Presentazione sul tema: "Async Programming EXT402 Raffaele Rialdi Visual Developer Security MVP MVP Profile"— Transcript della presentazione:

1 Async Programming EXT402 Raffaele Rialdi Visual Developer Security MVP MVP Profile http://snipurl.com/f0cv malta@vevy.com

2 Il thread è l'unità di esecuzione –Il processo è l'unità di isolamento (spazio di indirizzamento) –Ogni processo ha almeno un thread Il thread ha il suo TLS (Thread Local Storage) privato Il thread può non avere (default) oppure avere un security token (impersonation) –Passibile di "luring attack" o elevazione di privilegio Il thread ha una priorità Lo scheduler di Windows concede ad ogni thread una certa quantità di tempo di esecuzione che dipende –dalla priorità –dal numero di thread totali –dal tipo di OS (server vs workstation) –dal numero di CPU Un po' di termini... App Domain

3 Avviene fondalmentalmente in tre casi 1.Quando dal thread viene sospesa l'esecuzione chiamando Thread.Sleep oppure chiamando WaitOne, WaitAny, WaitAll (che vedremo dopo) oppure Win32 ==> (WaitForSingle/MultipleObject/s, MsgWaitForxxx) 2.Quando dal thread viene chiamata Win32 SwitchToThread() oppure Thread.Sleep(0) (identico) 3.Quando il quantum a disposizione del thread è terminato. Context switch

4 Context switch richiede circa 5000 istruzioni. Gli step tipici sono: 1.Entrare in Kernel Mode 2.Salvare i registri relativi al thread precedente 3.Acquisire il dispatch spinlock oggetto kernel che permette di gestire la concorrenza tra più CPU 4.Determinare il thread successivo da eseguire (se appartiene ad un altro processo, può essere ancora più costoso) 5.Lasciare il dispatch spinlock. 6.Scambiare in kernel mode lo stato dei thread precedente e successivo 7.Riprisitnare i registri relativi al nuovo thread 8.Uscire dal Kernel Mode Non abusare dei thread Azioni non eseguite in caso di Fibers

5 Perché lavorare in asincrono? Asincrono significa che l'esecuzione avviene in un contesto di esecuzione differente Usare più thread invece di più processi –i thread condividono lo stesso spazio di indirizzamento –si risparmia molta memoria (svchost.dll) –i thread fanno meno 'fatica' a comunicare rispetto ai processi Motivazioni per lavorere in asincrono –Per rendere responsiva la UI –Per dare modo all'utente di annullare un'operazione lunga –Per svolgere in modo parallelo dei task –... –Perché la pacchia è finita e i GHz non cresceranno più di tanto ma i 'core' si

6 Programmazione asincrona Creando esplicitamente un thread –Thread –Thread pool Oppure lasciando che sia il framework a crearlo per noi –Beginxxx –System.Threading.Timer –... In ogni caso entrano in gioco i thread

7 ThreadPool Meccanismo di riuso dei thread che minimizza i costi in performance Un solo ThreadPool per processo (non per-appdomain) Il pool viene creato con un minimo di 2 thread e non più di 50 (default modificabili) I thread del thread pool lavorano sempre in MTA. –se si vuole un thread in STA non si può usare il ThreadPool Per avviare un thread dal pool: ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), param);

8 System.Threading.Thread Crea esplicitamente un thread –Utile per creare un thread nella STA –Utile per creare un thread che vive molto a lungo –Non conveniente per creare thread che vivono vita breve (meglio il ThreadPool) Il minimo codice per creare un thread oppure (fx 2.0) Thread t = new Thread(new ThreadStart(ThreadProc)); t.Start(); Thread t = new Thread(new ThreadStart(ThreadProc)); t.Start(); Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); t.Start(param); Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); t.Start(param);

9 Proprietà più usate di System.Threading.Thread ApartmentState. Determina l'apartment COM nel quale far girare il thread (Default MTA) –Impostabile solo prima che il thread parta (TrySetApartmentState evita l'eccezione) –Per la main() si usano gli Attributi [STAThread], [MTAThread] –In Asp.net (default MTA) l'attributo aspcompat=true indica STA CurrentCulture. Impostazioni di currency, date, ora,... CurrentUICulture. Impostazioni sulla lingua della UI (MUI, risorse, etc.)

10 Proprietà più usate di System.Threading.Thread IsBackground. Se false l'applicazione in chiusura aspetta che il thread termini ManagedThreadId. Identificativo del thread o del fiber (dipende dall'applicazione host). Rende obsoleta la AppDomain.GetCurrentThreadId Priority. Determina la priorità del thread per lo scheduler di Windows [Flags] ThreadState. Legge lo stato in cui si trova il thread (avviato, fermato, etc.)

11 Metodi più usati di System.Threading.Thread Start/Suspend/Resume. Avvia/Sospende/Riavvia l'esecuzione del thread Sleep. Sospende il thread rinunciando al proprio quantum assegnato dallo scheduler di Windows. –Il numero di millisecondi indicato è il minimo per cui il thread non sarà eseguito Join. Sospende il thread chiamante fino a che quello chiamato termina –Join serve la message pump COM ma non aggiorna la UI AllocateDataSlot, GetData e SetData permettono l'accesso al TLS –Il CLR elimina e ripristina il TLS ad ogni cambio di AppDomain LocalDataStoreSlotSlot = Thread.AllocateDataSlot(); Thread.SetData(Slot, "Hello");... string str = Thread.GetData(Slot) as string; LocalDataStoreSlotSlot = Thread.AllocateDataSlot(); Thread.SetData(Slot, "Hello");... string str = Thread.GetData(Slot) as string;

12 Comunicazione con i thread I Thread di uno stesso processo vivono dentro lo stesso spazio di indirizzamento, quindi possono condividere la memoria –È quindi necessario un meccanismo per regolare l'accesso esclusivo ad una risorsa per non lasciarla in uno stato inconsistente. –Questo implica che l'accesso alla risorsa deve avvenire in tempi differenti e non contemporaneamente. Thread differenti eseguono codice su due differenti linee temporali. Spesso è necessario eseguire porzioni di codice di due (o più) thread in una sequenza –È quindi necessario un meccanismo per sincronizzarne l'esecuzione

13 Ciclo di vita di un thread I thread (così come i processi) non vanno killati se non in casi estremi –non vengono chiamati i distruttori –possono lasciare uno stato inconsistente nell'applicazione

14 Condivisione di memoria tra thread Istanza dati static (se classe o struct) definizione tipo (int, struct,class) Istanza new MyType ! OKOK OKOK !

15 Accesso esclusivo Critical Sections (Monitor). Oggetto del sistema operativo che permette di regolare l'accesso esclusivo ad una risorsa –Non condivisibile tra processi, è l'oggetto di sincronizzazione più performante –C# –VB.net lock(x) { Work(x); } lock(x) { Work(x); } Object obj = (Object)x; // eventuale boxing System.Threading.Monitor.Enter(obj); try { Work(x); } finally { System.Threading.Monitor.Exit(obj); } Object obj = (Object)x; // eventuale boxing System.Threading.Monitor.Enter(obj); try { Work(x); } finally { System.Threading.Monitor.Exit(obj); } SyncLock(x) Work(x) End SyncLock SyncLock(x) Work(x) End SyncLock

16 Tipologie di locking Operazioni garantite atomiche –Tutte le operazioni di grandezza pari ai registri CPU –System.Threading.InterLocked Add / Decrement (int e long) CompareExchange(T v1, T v2, T v3) Se v3==v1 ==> v1=v2 T res = Exchange(T v1, T v2) v1=v2, res=v1 System.Threading.ReaderWriterLock –Lock ottimizzato per molte letture e una sola scrittura –Ottimale dove la risorsa cambia poco frequentemente Il resto deve essere sempre protetto se è possibile che sia accesso da più thread

17 Accesso esclusivo - processi differenti Mutex è un oggetto kernel analogo per funzionamento al Monitor –Si condivide tra processi tramite nome –Il prefisso "Global\" indica che è globale dell'OS –Il default è "Local\" cioè relativo alla sola sessione attuale static void Main() { bool bNewInstance; Mutex Instance = new Mutex(true, @"Global\NomeUnico", out bNewInstance); if(!bNewInstance) return; Form1 f = new Form1(); Application.Run(f); Instance.ReleaseMutex(); Instance.Close(); } static void Main() { bool bNewInstance; Mutex Instance = new Mutex(true, @"Global\NomeUnico", out bNewInstance); if(!bNewInstance) return; Form1 f = new Form1(); Application.Run(f); Instance.ReleaseMutex(); Instance.Close(); }

18 Sincronizzazione AutoResetEvent e ManualResetEvent sono oggetti kernel che segnalano da un thread differente (anche se in processi diversi) che si è verificato l'evento –Classe base: EventWaitHandle AutoResetEvent ripristina automaticamente a "non segnalato" l'evento dopo le WaitOne ev.Set(); ev.WaitOne(); AutoResetEvent ev = new AutoResetEvent(false); // creazione e start thread secondari AutoResetEvent ev = new AutoResetEvent(false); // creazione e start thread secondari ev.WaitOne(); Thread sospesi Thread avviati

19 Sincronizzazione WaitHandle ha due metodi statici: WaitAll e WaitAny ev1.Set(); ev2.Set(); ev1.Set(); ev2.Set(); WaitHandle. WaitAny(evArray); WaitHandle. WaitAny(evArray); AutoResetEvent ev1 = new AutoResetEvent(false); AutoResetEvent ev2 = new AutoResetEvent(false); WaitHandle[] evArray = new WaitHandle[] {ev1, ev2}; // creazione e start thread secondari AutoResetEvent ev1 = new AutoResetEvent(false); AutoResetEvent ev2 = new AutoResetEvent(false); WaitHandle[] evArray = new WaitHandle[] {ev1, ev2}; // creazione e start thread secondari Thread sospeso Thread avviato WaitHandle. WaitAll(evArray); WaitHandle. WaitAll(evArray); oppure non segnalato segnalato

20 Sincronizzazione WaitOne, WaitAny, WaitAll hanno tutti altri due overload che prende un timeout per uscire dall'attesa senza aspettare l'evento (Int32 millisecondi o TimeSpan) L'handle al processo è un altro esempio di handle utilizzabile con questi metodi –Si può attendere in un thread secondario il termine di un processo lanciato precedentemente Semaphore è un altro oggetto kernel che funge da arbitro, analogo ai precedenti, che il numero di thread che possono contemporaneamente accedere ad una risorsa Race Conditions

21 Timer I timer sono tre: –System.Windows.Forms.Timer (usa la message pump) –System.Threading.Timer –System.Timers.Timer (usa internamente System.Threading.Timer) Per impostare scadenze successive è inutile usare più di unh timer –si ordina la lista di scadenze e si schedula la differenza tra la prima e DateTime.Now Al posto di usare un timer si può anche usare la scadenza di WaitHandle con eventi di supporto –Vedi esempio Esempio Timer

22 Accesso alla message pump di Windows La message pump delle finestre di Windows non può essere chiamata da thread diversi dal primario –GDI non rientrante –in fx 2.0 Control.CheckForIllegalCrossThreadCalls (versione debug) ci avvisa con un'eccezione Il modo canonico è quello di eseguire una Form1.Invoke invocando un delegate della form Esempio FormInvoke

23 La message pump in Windows È sempre necessario processare la coda dei messaggi –in caso negativo l'applicazione non può processare WM_PAINT –"Application is not responding" Il GDI non è rientrante –eredità del vecchio GDI 16 bit che non si è potuta cambiare –varaibili globali impediscono la rientranza in modo 'stabile' WM_PAINT WM_MOUSEMOVE WM_COMMAND WM_CUT WM_MOVE WM_TIMECHANGE WM_SETFONT WM_POWER WM_HELP WM_SETICON

24 BackgroundWorker Componente che permette di eseguire con semplicità un'elaborazione lunga in un thread separato –Si trascina sulla form il componente –Chiamando RunWorkerAsync si avvia l'elaborazione –Nell'evento DoWork si esegue l'elaborazione lunga Con ReportProgress si informa backgroundworker sulla percentuale di avanzamento Se CancellationPending è true, bisogna impostare e.Cancel=true ed uscire –L'evento ProgressChanged può aggiornare la UI direttamente –L'evento RunWorkerCompleted comunica Error = true indica un'eccezione del worker process Cancelled = true indica che è stata richiesta l'annullamento Altrimenti si aggiorna la UI sul risultato –Chiamando CancelAsync si chiede l'interruzione Esempio BGWorker

25 Invocazione asincrona di un metodo Il framework prevede un meccanismo semplificato per eseguire un metodo in un thread del thread pool –Metodi nella BCL che iniziano per BeginXXX Invocazione dei metodi dei web services lettura/scrittura su file nuove librerie di zip/unzip del fx 2.0.... molte molte altre –Creazione di un delegate al metodo ed uso del metodo BeginXXX al pari di quelle presenti nel framework

26 Invocazione asincrona Metodo 1: callback LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); sd.BeginInvoke(5, new AsyncCallback(Callback), sd); LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); sd.BeginInvoke(5, new AsyncCallback(Callback), sd); Parametro/i di Start metodo che riceve il risultato object da passare alla callback void Callback(IAsyncResult res) { StartDelegate sd = res.AsyncState as StartDelegate; int Result = sd.EndInvoke(res); } void Callback(IAsyncResult res) { StartDelegate sd = res.AsyncState as StartDelegate; int Result = sd.EndInvoke(res); } Recupero object della BeginInvoke Recupero risultato

27 Invocazione asincrona Metodo 2: attesa della fine LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); IAsyncResult res = sd.BeginInvoke(5, null, null); // altre operazioni nel thread principale... int Result = sd.EndInvoke(res); LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); IAsyncResult res = sd.BeginInvoke(5, null, null); // altre operazioni nel thread principale... int Result = sd.EndInvoke(res); Parametro/i di Start Informazioni sul risultato async Attesa e recupero risultato

28 Invocazione asincrona Metodo 3: attesa dell'evento LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); IAsyncResult res = sd.BeginInvoke(5, null, null); // altre operazioni nel thread principale... res.AsyncWaitHandle.WaitOne(); // attesa fine esecuzione int Result = sd.EndInvoke(res); LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); IAsyncResult res = sd.BeginInvoke(5, null, null); // altre operazioni nel thread principale... res.AsyncWaitHandle.WaitOne(); // attesa fine esecuzione int Result = sd.EndInvoke(res); Parametro/i di Start Informazioni sul risultato async Attesa e recupero risultato

29 Invocazione asincrona Metodo 4: attesa tramite boolean LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); IAsyncResult res = sd.BeginInvoke(5, null, null); while(!res.IsCompleted) { // altre operazioni nel thread principale... // Application.DoEvents()... solo per winform Thread.Sleep(10); } int Result = sd.EndInvoke(res); LongRunning lr = new LongRunning(100); StartDelegate sd = new StartDelegate(lr.Start); IAsyncResult res = sd.BeginInvoke(5, null, null); while(!res.IsCompleted) { // altre operazioni nel thread principale... // Application.DoEvents()... solo per winform Thread.Sleep(10); } int Result = sd.EndInvoke(res); Parametro/i di Start Informazioni sul risultato async recupero risultato Attesa termine esecuzione Esempio AsyncDelegate

30 Caliamo nella realtà WinForm, WPF, WCF, WF,.... tutte tecnologie che hanno e continueranno ad aver bisogno di un thread switch Che fare quindi se i metodi da invocare da thread differenti sono in numero consistente? –dichiarare il delegate –creare un metodo adatto –istanziare il delegate –invocarlo... IDEA! Esempio pazzo

31 Tre fasi in cui Microsoft Research sta lavorando: –Tools di analisi statica per trovare i bug sui deadlock –Nuove keyword nei linguaggi in modo da strutturare in modo organico il locking nel sorgente (design by contract) –Nuovi costrutti nei linguaggi che fungano da alternativa al locking (Transactional Memory, Concurs) Uno sguardo al futuro

32 Domande?


Scaricare ppt "Async Programming EXT402 Raffaele Rialdi Visual Developer Security MVP MVP Profile"

Presentazioni simili


Annunci Google