Tips & Tricks Roberto Brunetti [email protected] http://thinkmobile.it/blogs/rob Marco Frontini [email protected] http://thinkmobile.it/blogs/front Architettura • Mai scrivere il codice nel Click !!!!!!!! • Dopo i controlli sull’interfaccia specifica • Chiamare una classe che esegue il lavoro • Occhio al numero di oggetti caricati • Non usare GC.Collect() • Implementare IDisposable dalle classi che fanno uso di altre risorse • Usare .Dispose() dal chiamante (o using) • Come si fa per Connection al db, File etc etc Uso Corretto try/catch • Usare try/finally all’interno di try/catch: try { File.Open() try } { catch (FileNotFoundException File.Open() e) { } MessageBox.Show(“Casino finally sul file”); } { finally File.Close { } } File.Close catch } (FileNotFoundException e) { MessageBox.Show(“Casino sul file”); } Close / Minimize • I form si minimizzano (X) • Come le applicazioni CE • Share Violation da VS mentre copia dell’exe • Molte utility intercettano la X per chiudere effetttivamente l’applicazione (form) • PocketPlus / Pocket Controller • Restando in memoria • MinimizeBox = false • Mette OK nella ControlBox • Chiude la form • Non Logo-Compliant ! Stop Close • Per applicazioni sempre attive e bloccanti • Intercettare Form.Closing • (System.ComponentModel.CancelEventArgs e) • e.Cancel = true; • Occorre MinimizeBox = false • Deve chiudersi non minimizzarsi UI lenta • Il disegno dei bit sullo schermo non e’ velocissimo • Per riempire i controlli con molti dati • Visibile = False • Ciclo • Visible = True • Usare BeginUpdate / EndUpdate se supportati • Demo FillingComboVBRichClient • (HighResolutionTimer) Form Load • Sempre Lento ! • Obiettivo • Prima volta • Ridurre il tempo di caricamento • Successive volte • Azzerare il tempo Form Load first time (20% c.a.) • VS.NET 2003 • Costruttore chiama InitializeComponent • InitializeComponent • Controlli Quadrati (Panel, Tab, Form) • Sostituire con this.xxx.Bound = new Rectangle()) • Gerarchia • Usare figlio.Parent al posto di Papà.Add • E Top Down: prima il papà e poi il figlio • Occhio che il Designer rigenera sempre tutto • Agire subito prima del deploy • Fare classe Finta che blocca il designer • Tenere due form • Su quella “Auto” fare modifiche e ricopiare il “Vera” Form ReLoad • Form di dettaglio da aprire più volte • Definire static il costruttore • Che inizializza solo la prima volta la form • Definire costruttore privato • In pratica si tiene in memoria la form • Meno costruzione/distruzione oggetti ! • Il GC non può scaricare la form se c’è bisogno • Volendo si può precaricare da un background thread • Al termine del Load della prima form Collection di form • Mettere le istanze dei form in collection • Array – Collection Custom – etc... • Si possono precaricare all’inizio in background • Fra un attimo parliamo di thread • Si possono caricare alla prima richiesta • Occhio alla quantità di memoria occupata • Se troppa il GC potrebbe scaricare il codice compilato Form non-full screen • FormBorderStyle = None • Obbligatorio • Altri valori fanno tornare il form full screen a runtime • Ma ci perdiamo il bordo !!! • Override del metodo Paint • Disegnare noi il bordo • Più semplice di quanto si creda Forms Full-Screen & Controls • Managed • Text = “” • Menu = null/Nothing • …e se serve l’input panel o il menu? • Native – SHFullScreen • …e se l’utente usa l’help dell’input panel? • Managed OnDeactivate() • Native GetForegroundWindow • Non dimentichiamoci uno shortcut • Per chiudere in caso di manutenzione (magari con password) • Task List: come visualizzare una sola form Scrollable Something • System.Windows.Forms.ScrollableControl è una finta • Managed • Panel come container dei child Controls • Native • ScrollWindowEx + SW_SCROLLCHILDREN • E con la Second Edition • … ancora peggio… • Custom Control • Il designer di VS 2003 non li supporta • Nessun problema, lo inganniamo Display e Layout Funzionalità dei Device • Orientamento • Risoluzione • .NET Compact Framework 1.0 Service Pack 2 (oggi) • • • • Gestione automatica delle form scrollabili Evento Form.Resize Gestione automatica dell’alta risoluzione White paper su MSDN: Developing Screen Orientation-Aware Applications Display And Layout .NET Compact Framework 2.0 • Supporto all’orientamento • • • • Docking e Anchoring Proprietà AutoScroll – forms, panels Metodi Suspend/Resume Layout Metodo ChangeOrientation • • Supporto alla risoluzione Scaling automatico • Demo dopo con Fabio SIP • Display automatico su campo input • Controllo da codice • Aggiungere il controllo Software Input Panel • SIP.Enabled = true/false • Resize del form/controlli • • • • Intercettare EnableChanged Proprietà VisibleDesktop di tipo Rectagle Height e Width per sapere la dimensione Ctor per salvare la dimensione originale Versione .NET CF Installata • System.Environment.Version • Major / Minor / Revision / Build • N.B. I service Pack escono redistributable • Non aggiornano . Cab sotto VS 2003 • Si devono copiare i cab sull’emulatore • VS 2005 non è più così • Connessione con ActiveSync dell’emulatore ! • Da Desktop App.Path • Magari • OpenNETCF • Reflection • Assembly.GetExecutingAssembly().GetName().CodeBase • System.IO • Path.GetDirectoryName per strappare l’exe Registry • P/Invoke ? • OpenNETCF • Classe OpenNETCF.Win32.Registry • SottoClassi Dedicate • • • • ClassesRoot CurrentUser LocalMachine Users • CreateSubKey • OpenSubKey • DeleteSubkeyTree File di Configurazione <appSettings> <add key=“nome” value=“xxxx” /> </appSettings> • Da codice Namespace OpenNETCF.Configuration • ConfigurtionSettings.AppSettings[“nome”] • N.B. OpenNETCF 1.2 • Per applicazione Applicazione.exe.config • Per DLL Applicazione.dll.config • Solo per primo livello • 1.3 Applicazione.exe.config Threding in .NET CF Semplice Intro • Non usare il processore se non necessario • Non usare polling !!!! • Soprattutto per sincronizzare i thread • Il multithread aggiunge complessità • Per definizione un’applicazione multithread non va più veloce...anzi • Ma più sfruttare momenti di pausa • Perché aspettare i dati da un DB invece di fare qualcos’altro nel frattempo ? • Perché non eseguire operazioni in background mentre l’utente fa altro ? Threading Namespace • .NET CF 1.0 • • • • • Thread CurrentThread Priority Sleep Start • Foreground only ! • .NET CF 2.0 • • • • • • • • • Thread CurrentThread IsBackground Name Priority Abort Join Sleep Start • Fore e Back Thread.Creazione • .NET Compact Framework 1.0 • Creare e avviare thread è semplice Thread myThread = new Thread(new ThreadStart(MyWorkerThread)); myThread.Start(); private void MyWorkerThread() { while (! workerThreadDone) { // simulate some processing Thread.Sleep(1000); } } Thread.Creazione • .NET Compact Framework 2.0 • Creare e avviare thread è più semplice Thread myThread = new Thread(MyWorkerThread); myThread.Start(); private void MyWorkerThread() { while (! workerThreadDone) { // simulate some processing Thread.Sleep(1000); } } Demo Considerazioni • Abbiamo tre problemi nelle demo precedenti • Usiamo la variabile “i” • Se facciamo partire due thread andiamo in scrittura della stessa variabile • Lo abbiamo fatto solo per Demo • Se chiudiamo la App con il thread in corsa • La Form sembra si chiuda...fra poco • Se abbiamo bisogno di aspettare il thread prima di fare altre operazioni • Es Riempio Combo in parallelo ma prima di usarla il thread deve aver finito Application Shutdown • 1.0 solo Foreground Thread • L’applicazione termina solo quando tutti i thread foreground finiscono • Sembra che si chiuda ma i thread avviati proseguono • Evitiamo la chiusura • Oppure potremmo stoppare il thread • Ma in 1.0 non c’è Abort • Occorre usare una variabile - Polling ?!?!?! • OpenNETCF.Threading • ThreadEx • MonitorEx, Semaphore, EventWaitHandle 2.0 Abort • Possiamo chiedere a un thread .Abort • Otteniamo un’eccezione ThreadAbortException • Non facciamo Polling • 2.0 anche Background Thread • Terminati dal CLR se l’applicazione termina • Thread.Abort chiamato dal CLR • Per Default sono ForeGround • IsBackGround = true; Sapere quando ha finito • 1.0 AutoResetEvent • False prima di Start • .Set() alla fine del lavoro del Thread • .WaitOne() • 2.0 Join • Nessun AutoResetEvent da dichiarare • Ne serve 1 per ogni thread (lavoro da fare) • Nessuna variabile Aggiornare UI da altri Thread • Mai aggiornare i controlli direttamente private void WorkerThread() { statusBar1.Text = “Sto facendo questo"; while (!workerThreadDone) { Thread.Sleep(1000); } } 1.0 • Nessun eccezione...pizza e basta • Control.Invoke • Sincrono e senza parametri private string statusBarText; private void WorkerThread() { statusBarText = "WorkerThread active"; this.Invoke(new EventHandler(UpdateStatusBar)); while (!workerThreadDone) { Thread.Sleep(1000); } } private void UpdateStatusBar(object sender, EventArgs e) { statusBar1.Text = statusBarText; } 2.0 • .NET CF 1.0 • • Invoke (delegate) • .NET CF 2.0 • • • • • • Invoke (delegate) Invoke (delegate, object[]) BeginInvoke (delegate) BeginInvoke (delegate, object[]) EndInvoke () NotSupportedException N.B. 2.0 • • • Eccezione se usato non correttamente Asincrono Parametri...non dobbiamo fare più variabili 2.0 private void WorkerThread() { statusBar1.Text = “Sto Facendo…calma"; while (!workerThreadDone) { Thread.Sleep(1000); } } NotSupportedException 2.0 • Control.(Begin)Invoke private delegate void UpdateSB (string statusBarEntry); private void WorkerThread() { UpdateSB sbUpdater = UpdateStatusBar; this.Invoke(sbUpdater, new object[] {"WorkerThread active"}); while (!workerThreadDone) { Thread.Sleep(1000); } } private void UpdateStatusBar(string statusBarInfo) { statusBar1.Text = statusBarInfo; } Occhio alla chiusura !!! • 1.0 • Foreground thread • Dispose del Form uccide i controlli • E il delegate fa la pizza • 2.0 • • • • == 1.0 Background thread Richiesto abort da CLR Intercettare ThreadAbortException e fermare le invoke • Potrebbe essere comunque troppo tardi • Oppure evitare la chiusura come abbiamo visto Non tutti sanno che … • • • • • • • • Retargetable flag attribute Typed DataSets HTTP Server Migrazione da eMbedded Visual Tools Obfuscation Compilazione da riga di comando Control Design – RuntimeAssemblyAttribute String.Intern() Design guidelines di Microsoft • Pocket PC 2003 SDK • SmartPhone 2003 SDK How To • Custom TextBox • managed o native ? • Device ID • KernelIoControl() - IOCTL_HAL_GET_DEVICEID • Workaround • Toolbar • ImageList • ListView con Second Edition e SP2 • DEMO #5 Fuori in 60 secondi Creare una gestione dati in 60’’ DataSoul Framework © 2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY. Content created by 3 Leaf Solutions