22

Dec

Demo 11 – Multithreading e accesso concorrente

Mi sforzo sempre di accennare brevemente alla gestione dei thread, perchè reputo che sia fondamentale saperne qualche dettaglio essenziale. Ci sono applicazioni che possono girare tutte nello stesso Thread (ma sono poche), altre che girano nello stesso thread provocando freeze tremendi, ed altre che proprio, by design, non possono essere implementate senza la gestione del multithreading. Oggi analizziamo il multithreading sotto il cappello della concorrenza (anche perchè di parallelismo, sul mobile, finora non ne abbiamo mai visto).

Rudimenti

Nel modello Windows Forms per mobile, ogni controllo gira sotto lo stesso thread padre che ha generato il form: ciò significa che se qualcuno osa mettere del codice long-running all’interno di un evento TextChanged di una TextBox o simili, ottiene il freezing totale dell’applicazione, fino a fine computazione.

Se noi invece dessimo questo compito da eseguire ad un thread a parte, allora sarebbe sicuramente gestito parallelamente come abbiamo sempre sperimentato. Quindi partiamo dal primo semplice e banale caso: mi serve un thread per l’esecuzione di un mero processo computazionale.

Variante 1: Multithreading per computazioni lunghe

Iniziamo con il creare un metodo che, per esempio, spara su un file i primi 1000 numeri naturali:

image

Se lo facessimo eseguire al click di un pulsante, probabilmente avremmo solo un leggerlo stop per qualche millisecondo; ma se provassimo ad aumentare quel 1000 a 100000 sicuramente vedremmo l’applicazione congelarsi all’istante. Perciò come facciamo partire questo metodo? Così:

image Oppure anche così, metodo che logicamente ha più senso (i ThreadPool servono infatti per eseguire tasks indipendenti):

image

Variante 2: Multithreading con modifica dei controlli forms

Questa è certamente la variante più fastidiosa, dove è necessario un bagaglio di conoscenza maggiore prima di andare avanti. Infatti, se non si presta attenzione, si incappa in poco tempo in questo problema:

image La soluzione da adottare è quella di usare un meccanismo di notifica asincrono tra thread, con le Invoke direttamente sul controllo da modificare… eh?!?!? Meglio fare un esempio per essere più concreti, tenendo in considerazione la regola che:

Se crei un controllo in determinato Thread, solo il thread proprietario può accedervi senza causare una eccezione

Quindi cosa si fa? Questo:

image

Altri concetti utili

BISOGNA sapere come fermare i thread e come aspettarli, come minimo, per utilizzarli in modo più complesso. Sono sempre più convinto che i framework per la parallel computing faranno in modo che l’utente si interessi sempre meno della gestione low-level dei thread: tuttavia, qualche base non fa male.

  • Metodo Start: fa partire il thread.
  • Metodo Join: il Thread che lo invoca (su un Thread target) “aspetterà” la fine dell’esecuzione del thread target su cui l’ha invocato; dopodichè, continuerà la sua esecuzione. Utile per la sincronizzazione tra Threads.
  • Metodo Abort: serve per terminare un Thread. Ma in che modo? Solleva una eccezione all’interno del codice del Thread, cosìcchè il programmatore, gestendola, possa capire quando si chieda la terminazione del Thread (molto elegante).

That’s All, o quasi.

by Roberto Freato on 12/22/2009
Post archive