Programare Visual Studio -...

46
Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010 Document no. Version no.: 0.1 CR no.: Author: Lucian Nita Programare Microsoft Visual Studio .NET Lucrari de laborator Version no.: 1 Page 1 of 46

Transcript of Programare Visual Studio -...

Page 1: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Programare MicrosoftVisual Studio .NET

Lucrari de laborator

Version no.: 1 Page 1 of 46

Page 2: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Cuprins

1 INTRODUCERE......................................................................................................................................................4

2 PREZENTAREA MEDIULUI DE PROGRAMARE VISUAL STUDIO .NET.................................................5

2.1 PRINCIPALELE FERESTRE DE LUCRU DIN VISUAL STUDIO...................................................................................72.2 COMENZILE DE LUCRU UTILIZATE IN VS............................................................................................................7

3 DEFINIREA CLASELOR IN OOP........................................................................................................................9

3.1 PROPRIETATI, CONSTRUCTORI. TIPUL ENUM SI DATETIME.................................................................................93.2 INSTANTIEREA CLASELOR.................................................................................................................................103.3 CONSTRUCTORI PRIVATI. OBIECTELE TIMER SI RANDOM.................................................................................11

4 PREZENTAREA DATELOR................................................................................................................................15

4.1 SOLUTII CU PROIECTE MULTIPLE. IERARHIZAREA PROIECTELOR......................................................................154.2 FEREASTRA OUTPUT.........................................................................................................................................164.3 PROGRAMARE BAZATA PE EVENIMENTE. OBIECTELE "DELEGATE" SI "EVENT"...............................................174.4 PREZENTAREA DATELOR IN DATAGRID.............................................................................................................19

4.4.1 Controalele de tip GUI nu sunt thread-safe.............................................................................................214.5 CONTROALE VIZUALE: CHECKBOX, TEXTBOX. CLASA DICTIONARY..............................................................23

5 SALVAREA INFORMATIILOR IN BAZA DE DATE.......................................................................................30

5.1 CREAREA BAZEI DE DATE SQLITE....................................................................................................................305.2 DATA ACQUISITION LAYER : INTERFATA INTRE BAZA DE DATE SI APLICATIA GUI...........................................31

5.2.1 Definirea string-ului de conectare la baza de date in pagina de proprietati a proiectului.....................325.3 CLASA DE INTERFATA CU BAZA DE DATE..........................................................................................................33

5.3.1 Salvarea informatiilor in baza de date.....................................................................................................335.3.2 Citirea informatiilor din baza de date......................................................................................................36

6 TRANSMITEREA DATELOR INTRE APLICATII. SOCKET TCP/IP.........................................................40

6.1 OBIECTUL TCPCOMMCLIENT...........................................................................................................................416.1.1 Impachetarea datelor pentru transmisie..................................................................................................426.1.2 Crearea unui nou fir de executie pentru fiecare dialog cu serverul........................................................436.1.3 Trimiterea datelor catre server................................................................................................................446.1.4 Functia Dispose inchide firele de executie suspendate............................................................................45

6.2 OBICETUL TCPCOMMSERVER..........................................................................................................................46

Version no.: 1 Page 2 of 46

Page 3: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Lista de figuri

Figura 1: Visual Studio apare ca devenv.exe in lista de procese din Task Manager.......................................5Figura 2: Crearea unui nou proiect de tip "Console Application" in Visual Studio .NET..................................6Figura 3: Principalele ferestre de lucru ale mediului Visual Studio..................................................................7Figura 4: Clasa "SensorBase" si enumerarea "SensorType"..........................................................................9Figura 5: Constructorii clasei SensorBase....................................................................................................10Figura 6: Selectarea unei valori dintr-o enumerare.......................................................................................10Figura 7: Instantierea clasei "SensorBase" folosind constructorul implicit.....................................................11Figura 8: Constructorii clasei PumpSensorValues........................................................................................12Figura 9: Functia de generare si afisare a valorile aleatoare pentru senzori.................................................13Figura 10: Intantierea clasei "PumpSensorValues" si pornirea ceasului.......................................................13Figura 11: Selectarea unui proiect ca referinta pentru proiectul curent.........................................................15Figura 12: Lansarea in executie a functiei de simulare a senzorilor..............................................................16Figura 13: Fereastra Output afiseaza mesajele trimise la consola................................................................16Figura 14: atasarea functiei "bTest_Click" la evenimentul "bTest.Click"........................................................17Figura 15: Definirea obiectelor de tip delegate si event in clasa de generare a datelor de masurare...........17Figura 16: Lansarea evenimentului "newSensorValueEvent".......................................................................18Figura 17:Atasarea functiei "OnNewSensorValueHandler" la evenimentul "newSensorValueEvent"............18Figura 18:Valorile primite prin eveniment de la clasa "PumpSensorValue" sunt afisate in MessageBox......19Figura 19: Controlul DataGridView din ToolBox............................................................................................19Figura 20:Setarea sursei de date pentru gridul de afisare............................................................................20Figura 21: Popularea listei sensorValueList si setarea ei ca DataSource pentru grid...................................21Figura 22: Eroare: un alt thread acceseaza datagridul.................................................................................21Figura 23: Fereastra principala de prezentare a datelor cu datagrid-ul legat la lista de valori......................23Figura 24: Adaugarea codului de pacient in clasa cu valorile senzorilor.......................................................24Figura 25: Patient code trebuie adaugat si in clasa PumpSensorValues......................................................24Figura 26: Evenimentul "newSensorValueEvent" include si codul de pacient...............................................24Figura 27: Adaugarea coloanei PatientCode in datagrid...............................................................................25Figura 28: Fereastra DataPresentation cu butoanele de startare si oprire a monitorizarii............................25Figura 29: Enumerarea ce include codurile de pacienti................................................................................26Figura 30: Atasarea unei enumerari la un CheckBox....................................................................................26Figura 31: Codul aferent butonului "Start Monitoring"...................................................................................26Figura 32: Functia StartPumping cu parametrii cod pacient si perioada de timp..........................................27Figura 33: Oprirea monitorizarii pentru un pacient si eliminarea lui din dictionarul pacientilor activi.............28Figura 34: Crearea bazei de date “PatientData” in SQLite Administrator......................................................30Figura 35: Crearea tabelului “PatientData” pentru salvarea datelor ce vin de la pacienti..............................31Figura 36: Adaugarea proiectului “DataStore” de tip “Class Library” la solutie..............................................32Figura 37: Definirea string-ului de conectare la baza de date SQLite in pagina de proprietati a proiectului. 33Figura 38: Functia de inserare a unei valori de masurare in baza de date...................................................34Figura 39: Tratarea evenimentului “newSensorValueEvent”: salvare in baza si afisare in datagrid..............35Figura 40: Comanda SQL de vizualizare a datelor din tabela PatientData...................................................35Figura 41: Vizualizarea datelor din baza in SQLite Administrator.................................................................35Figura 42: Fereastra DataPresentation dupa ce s-a adaugat sectiunea de filtrare......................................36Figura 43: Functia de citire din baza de date a datelor de masurare pentru un pacient si o zi stabilita........37Figura 44: Proiectul “CommonReferences” contine toate definitiile particulare ale tipurilor de date.............38Figura 45: Afisarea valorilor din baza de date...............................................................................................39Figura 46: Functia handler pentru butonul “Display Received Data”.............................................................39

Version no.: 1 Page 3 of 46

Page 4: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

1 Introducere

Scopul lucrarilor de laborator prezentate in acest document este de familiariza studentul cu mediul deprogramare Visual Studio .NET si aplicarea practica a cunostintelor prezentate la curs.

In acest scop, se propune in cele ce urmeaza realizarea unei miniaplicatii numite "HealthMonitor" care samonitorizeze de la distanta starea unui pacient cu probleme de sanatate, in sensul ca pacientul poate saramana acasa purtand cu el diversi senzori de masurare a bio-parametrilor (temperatura, ritm cardiac,glicemie, etc) si aceste valori sunt trimise prin internet la cabinetul doctorului care urmareste astfel stareapacientului si se deplaseaza numai la aparitia unei alarme. Ce presupune aceasta monitorizare?

Citirea parametrilor bio Salvarea valorilor masurate intr-o baza de date locala Transmisia valorilor la aplicatia ce ruleaza in cabinetul doctorului Afisarea acestor valori sub forma grafica sau text pentru ca doctorul sa poata trage concluziile

corecte referitoare la starea de sanatate a pacientului

Prin implementarea acestor taskuri, studentul va trebui sa-si insuseasca si sa lucreze cu urmatoareleconcepte:

Definirea claselor in OOP Instantierea claselor Mostenire Controale grafice Salvarea datelor in baza de date Comunicatii TCP/IP Multithreading Programare bazata pe evenimente ...

Evident ca aceste concepte nu pot fi acoperite in totalitate intr-un numar atat de mic de ore, dar acestexemplu poate reprezenta un punct de plecare pentru dezvoltarea de alte aplicatii serioase si aprofundareacunostintelor legate de programare obiect si Visual Studio .NET.

Version no.: 1 Page 4 of 46

Page 5: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

2 Prezentarea mediului de programare Visual Studio .NET

Mediul Visual Studio se deschide prin lansarea in executie a programului "C:\Program Files\Microsoft VisualStudio 9.0\Common7\IDE\devenv.exe". Trebuie retinut numele programului "devenv.exe" deoarece de multeori este utila sa deschidem aplicatia "Task Manager" din Windows si sa analizam modul de ocupare amemoriei si a microprocesorului in timpul rularii unui program. Faptul ca apare "devenv.exe" in capul listeidin tab-ul "Processes" cu o portiune mare de memorie utilizata, inseamna de multe ori ca programul aramas agatat pe un fir de executie infinit si trebuie oprit din TaskManager.

Figura 1: Visual Studio apare ca devenv.exe in lista de procese din Task Manager

Dupa lansarea VS, primul pas este de a deschide un proiect deja existent pe dicul local, sau putem crea unnou proiect (meniul File/New/Project..")

Version no.: 1 Page 5 of 46

Page 6: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 2: Crearea unui nou proiect de tip "Console Application" in Visual Studio .NET

Putem alege din mai multe tipuri de proiecte, dupa cum urmeaza: Windows Form application: este pentru dezvoltarea de aplicatii de tip GUI, bazate pe ferestre,

controale grafice, etc. WPF Application: dezvolta acelasi tip de aplicatii de tip GUI, dar bazate pe noua tehnologie WPF

(Windows Presentation Foundation) ce expune posibilitati mult mai largi de desenare grafica a interfetelor utilizator. WPF lucreaza cu limbajul XAML prin care se pot descrie imagine grafice de peecran. Folosind acest limbaj, utilizatorul are posibilitatea sa deseneze interfata grafica intr-o aplicatie specifica de desenare, exporta imaginea in format XAML si aceasta se importa in Visual Studio unde i se poate atasa evenimente si logica necesara aplicatiei.

Console Application: cel mai simplu proiect, nu are interfata grafica, este foarte util in testarea rapida a unor concepte de tip OOP.

Windows Service: dezvoltarea unui serviciu Windows. Serviciile sunt acele aplicatii care pornesc automat la deschiderea calculatorului si ofera suport in background pentru diverse functionalitati alesistemului. De exemplu, baza de date Oracle lucreaza ca un serviciu, porneste odata cu sistemul sideschide un "Listener" ce asculta in mod permanent la un port pentru a raspunde eventualelor comenzi SQL trimise de un client.

Proiecte de tip "Library": nu au interfata cu utilizatorul, nu pot fi pornite direct pentru ca nu contin functia "Main". Ele sunt folosite doar pentru crearea diverselor functii de biblioteca ce vor fi utilizate in programele de tip "application". Librariile sunt salvate pe disc sub forma de fisiere DLL ce trebuie importate in spatiul de lucru al proiecteor ce vor face apel la ele.

Version no.: 1 Page 6 of 46

Page 7: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

2.1 Principalele ferestre de lucru din Visual Studio

Dupa deschiderea unui proiect, Visual Studio afiseaza un ecran de lucru ce cuprinde urmatoarele ferestre utile:

Figura 3: Principalele ferestre de lucru ale mediului Visual Studio

Fereastra "Toolbox": contine majoritatea controalelor utilizate in crearea aplicatiilor: butoane,TextBox-uri, grid-uri, conexiuni,etc. Sunt foarte multe controale implicite ale mediului VS, dar pot fiadaugate de asemenea alte controale din diverse librarii sau instalari de aplicatii.

Fereastra de editare a codului de program: aici se introduce efectiv codul sursa al programului Fereastra "Solution Explorer" afiseaza structura solutiei: proiectele ce apartin de aceasta solutie,

proprietatile fiecarui proiect in parte, fisierele ce compun proiectul. Properties: este fereastra ce afiseaza proprietatile si evenimentele asociate obiectului curent

selectat in pagina de lucru Error List: listeaza erorile aparute la compilarea sau executia programului

2.2 Comenzile de lucru utilizate in VS

Comenzile des folosite in editarea si rularea unui program sunt: F5: compileaza si lanseaza in executie programul curent (in modul Debug) CTRL+S: salveaza fisierele de lucru

Version no.: 1 Page 7 of 46

Page 8: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

F6 (Build solution): compileaza solutia SHIFT+F5: opreste executia programului din modul Debug F10: executie pas cu pas (functia apelata se considera a fi un pas) F11: executie pas cu pas cu intrarea in functia apelata F9: defineste sau sterge un breakpoint in linia curenta

Version no.: 1 Page 8 of 46

Page 9: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

3 Definirea claselor in OOP

3.1 Proprietati, Constructori. Tipul Enum si DateTime

Se deschide mediul VS si creaza un nou proiect de tip "Console Application" numit "Test OOP". Se creeazaun nou folder in cadrul proiectului numit "Sensor" si in acest folder se defineste o noua clasa numita"SensorBase".

In cadrul acestei clase se definesc urmatoarele componente: Membri privati: type, value, timeStamp Proprietatile publice Type, Value, TimeStamp Constructorii:

- Implicit- public SensorBase(SensorType type, double value, DateTime timeStamp)- public SensorBase(SensorType type, double value, string timeStamp)

Figura 4: Clasa "SensorBase" si enumerarea "SensorType"

Version no.: 1 Page 9 of 46

Page 10: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 5: Constructorii clasei SensorBase

Lista de senzori potentiali cu care poate lucra programul este tinuta de o enumerare publica numita"SensorType". Enumerarile sunt constructii simple in care se pot da nume sugestive pentru numerelenaturale. De exemplu, este mult mai sugestiv sa primesti un parametru numit "HeartRate" decat numarul 2cat reprezinta acel parametru. Mai mult, daca se sterge sau se adauga un termen din enum, programul nuse modifica cu nimic, in continuare functia va primi parametrul "HeartRate", chiar daca acum acelparametru are valoarea 1. Alegerea unei valori din enum se face simplu, se scrie numele enum-ului si se alege valoareacorespunzatoare:

Figura 6: Selectarea unei valori dintr-o enumerare

Se observa ca in lista de proprietati a clasei proprietatea TimeStamp (timpul la care s-a facut masurarea)apare de doua ori. Prima varianta TimeStamp primeste si returneaza o clasa de tip DateTime, iar a douavarianta primeste un string si converteste acel string intr-o structura DateTime. Conversia unei date in stringse face cu metoda ToString (timeStamp.ToString("dd-MMM-yy HH:mm") ), metoda ce primeste caparametru stringul de formatare a datei calendaristice. Conversia inversa se face cu functia statica a claseiDateTime numita ParseExact :DateTime.ParseExact(value, "dd-MMM-yy HH:mm",CultureInfo.InvariantCulture)

3.2 Instantierea claselor

Se deschide fereastra programului principal (Program.cs) si se scrie codul pentru instantierea claseiSensorBase folosind constructorul implicit. Dupa crearea obiectului "sensor1" se folosesc proprietatileacestuia pentru introducerea valorile de masurare (Type, TimeStamp si Value). Toate aceste valori seafiseaza apoi la consola prin apelul functiei DisplaySensorValue. Aceasta functie primeste doi parametri:

Version no.: 1 Page 10 of 46

Page 11: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

o un string numit "headerText" care va fi afisat in capul listei de valorio o instanta a clasei "SensorBase" care contine informatiile de afisat

Figura 7: Instantierea clasei "SensorBase" folosind constructorul implicit

Sa se defineasca un alt obiect de tip "SensorBase", dar utilizand de data aceasta constructorul cuparametri

Sa se afiseze valorile acestui obiect prin apelul functiei "DisplaySensorValue()". Intrebare: de ce a fost necesar sa se declare functia "DisplaySensorValue()" de tip static? Stergeti

atributul "static" din definitia functiei si observati rezultatul.

3.3 Constructori privati. Obiectele Timer si Random

Cum nu avem senzorii in mod efectiv, va trebui sa construim o clasa care sa simuleze functionarea reala aacestor senzori. Aceasta clasa va trebui sa instantieze in mod aleatoriu un senzor din lista "SensorType" siapoi sa genereze o valoare aleatoare intr-un domeniu specific acelui senzor:

Temperatura poate varia intre 36 si 40 de grade Glicemia intre 80 si 300 mg/dl Pulsul inimii intre 30 si 200

Functia de simulare trebuie sa creeze aceasta valoare aleatoare in mod continuu cu o frecventa data defunctia principala Main.

Version no.: 1 Page 11 of 46

Page 12: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

In folderul "Sensor" se creeaza o noua clasa numita "PumpSensorValues". Aceasta va avea doar un singurconstructor public, cel ce primeste numarul de secunde intre doua valori ale senzorilor.

Figura 8: Constructorii clasei PumpSensorValues

Constructorul implicit va fi declarat privat pentru a nu permite instantierea unei clase fara sa se stabileascaperioada intre doua valori.

Incercati sa creati un obiect de tipul "PumpSensorValues" prin constructorul implicit si observatieroarea generata de VS

In constructorul clasei sunt create doua obiecte de uz general. Prima clasa instantiata este de tipul Random. Acesta clasa este folosita pentru generarea numereloraleatoare. Se instantiaza o singura data la intrarea in constructor si se poate apela oriunde in programpentru a obtine un numar aleator intre doua limite date. Generarea numarului aleator se face prin apelulfunctiei Next cu cele doua variante:

Next(intMax): genereaza un intreg aleator mai mic decat intMax Next(intMin, intMax): numarul aleator este cuprins intre intMin si intMax.

Al doilea obiect utilizat este de tipul System.Timers.Timer. Acest obiect lucreaza ca un ceas ce poate fiprogramat sa apeleze o functie periodic la un interval de timp dat. De fapt, la sfarsitul fiecarui interval detimp, timerul va genera un eveniment "Elapsed" la care noi trebuie sa ne abonam ca sa-l interceptam inmometul emiterii:timerBase.Elapsed += new ElapsedEventHandler(timerBase_Elapsed);Functia ce va fi apelata la fiecare tact al timerului este "timerBase_Elapsed". In aceasta functie trebuie saselectam in mod aleator un tip de senzor si sa-i dam o valoare, apoi sa afisam proprietatile senzorului laconsola.

Version no.: 1 Page 12 of 46

Page 13: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 9: Functia de generare si afisare a valorile aleatoare pentru senzori

Tot ce mai trebuie facut ca sa apara valorile la consola, este sa instantiem clasa PumpSensorValues si sa pornim ceasul din clasa respectiva:

Figura 10: Intantierea clasei "PumpSensorValues" si pornirea ceasului

Nu trebuie uitat la iesirea din program sa se opreasca ceasul pentru a nu mai trimite evenimente pe care sanu le intercepteze nimeni.

Intrebare: de ce am putut apela functia "DisplaySensorValues" in clasa "PumpSensorValues" farasa am vreo instanta la clasa "Program" ?

Version no.: 1 Page 13 of 46

Page 14: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Functiile StartPumping si StopPumping sunt urmatoarele:

public void StartPumping() { timerBase.Start(); } public void StopPumping() { timerBase.Stop(); }

In functia "StartPumping()" pornesc ceasul timerBase si acesta imi va trimite evenimente la fiecare "Interval" de timp."StopPumping" trebuie apelata la sfarsitul programului pentru a opri ceasul sa mai trimita evenimente.

Version no.: 1 Page 14 of 46

Page 15: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

4 Prezentarea datelor

4.1 Solutii cu proiecte multiple. Ierarhizarea proiectelor

Pana acum am reusit sa generam date pentru senzorii de masurare si sa le afisam in fereastra de tipconsola. Dar acest tip de afisare nu este convenabila pentru doctor. Doctorul ar avea nevoie de un ecrancare sa-i afiseze valorile sosite continuu de la senzor, sa le poata sorta dupa tipul de senzor, sa-i fiesemnalate alarme in cazul unei valori ce depaseste anumite limite.

In acest scop vom dezvolta un nou proiect de tip Windows Form Application care va avea drept scopafisarea intr-o maniera grafica a rezultatelor de masurare.Mai intai, se redenumeste solutia in "HealthMonitor" (click dreapta pe numele solutiei si alegem meniul"Rename"), iar proiectul TestOOP se redenumeste "SensorInput". Deci ne propunem o solutie pentrumonitorizarea starii de sanatate a pacientului, iar in cadrul acestei solutii proiectul deja construit are rol de asimula functionarea reala a senzorilor.

Se deschide un nou proiect in cadrul solutiei pentru prezentarea datelor venite de la senzori. Acest nouproiect se denumeste "DataPresentation" si se alege sa fie proeictul de pornire a solutiei. Cand o solutiecontine mai multe proiecte trebuie ales proiectul de pornire, cel ce va lansa functia Main().Acest nou proiect trebuie sa afiseze datele furnizate de celalalt proiect (SensorInput). Totusi, proiectele suntindependente si nu se pot apela in mod direct functii dintr-un proiect in altul. De aceea,trebuie alcatuita oierarhie de proiecte, in care un proiect poate face apel la clasele dintr-un alt proiect aflat pe o ramurainferioara in cadrul ierarhiei. Includerea unui proiect copil in cadrul ierarhiei se face prin adaugarea aceluiproiect la referintele proiectului tata. Se face click dreapta pe "References" la proiectul "DataPresentation"si se alege Add Reference:

Figura 11: Selectarea unui proiect ca referinta pentru proiectul curent

Referintele pot fi adaugate din universul .NET unde se gasesc majoritatea bibliotecilor de programe utile,sau din tab-ul "COM" ce contine controale particularizate, sau "Projects" unde sunt listate toate proiectelecurente ale solutiei curente.

Version no.: 1 Page 15 of 46

Page 16: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Se alege tab-ul "Projects" si se selecteaza proiectul "SensorInput" pentru a se adauga la referinteleproiectului curent.

Din acest moment proiectul "DataPresentation" poate instantia si utiliza toate clasele publice declarate inproiectul "SensorInput".

4.2 Fereastra Output

Se modifica constructorul proiectului "DataPresentation" pentru a lansa in executie functia "StartPumping"din clasa "PumpSensorValues":

Figura 12: Lansarea in executie a functiei de simulare a senzorilor

Chiar daca functia de simulare a senzorilor a pornit, in fereastra "DataPresentation" nu se vede nimic. Nicinu are cum, din moment ce functia de simulare trimite valorile generate la consola. Iar acum consola nueste vizibila pentru ca proiectul curent "DataPresentation" este de tip "Windows Form Application" si nuafiseaza consola. Totusi, putem vedea toate mesajele trimise la consola in timpul executiei unui proiect daca se activeazafereastra "Output" (meniul View/Output din VS). Aceasta fereastra se deschide in timpul executieiprogramului si afiseaza mesajele de consola ale aplicatiei:

Figura 13: Fereastra Output afiseaza mesajele trimise la consola

Version no.: 1 Page 16 of 46

Page 17: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

4.3 Programare bazata pe evenimente. Obiectele "Delegate" si "Event"

Am vazut ca clasa "PumpSensorValues" afiseaza datele doar la consola. Si totusi, noi am dori ca acestedate sa fie afisate de fereastra "DataPresentation". In schimb, "PumpSensorValues" nu are nici o informatiedespre clasa container in care va fi utilizata, deci nu are acces la nici un obiect din aceasta clasa. Esteaceeasi problema pe care o are obiectul "Button" dintr-o forma oarecare. In momentul cand utilizatorul faceclick pe buton, acesta ar trebui sa execute o actiune in clasa container, cea care il contine. Dar evident,butonul nu stie nimic despre clasa container, el este un obiect din biblioteca .NET si este instantiat in mii deaplicatii de tipul "Windows Form".

Tot ce poate sa faca un buton in momentul cand user-ul face "click" este sa lanseze evenimentul "Click".Daca este cineva sa-l asculte (adica s-a scris o functie care sa prinda evenimentul) atunci actiunea click vaavea afect, altfel evenimentul se pierde in eter. Se poate face o asemanare cu actiunile unui catel de paza.Catelul de paza (ca si butonul) cand se naste, nu stie unde va pazi si cine-l va asculta. Daca este pus sapazeasca o vie de exemplu, tot ce poate el este sa faca galagie, adica sa emita evenimente (in cazul defata evenimentul "Thief_Inside"). Daca este cineva sa-l asculte bine, daca nu, evenimentele se pierd.

Pentru a putea lansa si prinde evenimente, trebuie realizate cateva actiuni: Definirea obiectulului "Delegate": reprezinta amprenta functiei care trebuie sa prinda acel

eveniment. Definirea obiectulului "Event": este evenimentul propriu-zis. Lansarea evenimentului Prinderea evenimentului de functia "handler"

Toate aceste actiuni se fac automat cand se face double-click pe un buton in fereastra de design. VS-ulcreeaza automat o functie (handler) care sa trateze evenimentul trimis de buton si tot ce avem noi de facuteste sa introducem cod in acea functie. Daca ne uitam in background (Designer.cs), observam ca in acelfisier ,VS-ul introduce cod pentru legarea evenimentului la functie:

Figura 14: atasarea functiei "bTest_Click" la evenimentul "bTest.Click"

Revenim la aplicatia noastra si sa parcurgem pasii pentru lansarea si prinderea evenimentului ce anunta o noua valoare de la senzori.Mai intai, in clasa ce pompeaza date definim delegatul si evenimentul:

Figura 15: Definirea obiectelor de tip delegate si event in clasa de generare a datelor de masurare

Intai se defineste delegatul in afara oricarei clase. Este ca orice definitie de functie, numai ca i se pune infata termenul "delegate". In acest fel se defineste amprenta functiei care trebuie sa prinda evenimentul.Evenimentul se declara in interiorul clasei si trebuie sa fie public pentru a fi cunoscut si in afara clasei.Lansarea acestuia se face simplu, este ca un apel de functie:

Version no.: 1 Page 17 of 46

Page 18: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 16: Lansarea evenimentului "newSensorValueEvent"

Intotdeauna, inainte de lansare trebuie verificat daca evenimentul este diferit de null. Un eveniment este nulpana in momentul cand se ataseaza un handler la el. Daca nu are atasat nici un handler care sa-lintercepteze, nu are sens sa se trimita evenimentul, de aceea VS-ul il mentine nul.

Atasarea handler-ului la eveniment se face in clasa container "DataPresentation":

Figura 17:Atasarea functiei "OnNewSensorValueHandler" la evenimentul "newSensorValueEvent"

In constructorul clasei "DataPresentation" se instantiaza clasa "PumpServerValues(3)", se porneste functiade generare a datelor (StartPumping) si se ataseaza handlerul la eveniment.La fiecare 3 secunde functia "StartPumping" va genera un eveniment avand valorile senzorului ca argumentcare in final va fi tratat in handler. Pentru moment, handler-ul doar afiseaza un "MessageBox" cu valorilesenzorului.

Dupa lansarea in executie a proiectului, in fereastra clasei "DataPresentation" va aparea la fiecare 3secunde un mesaj cu valorile primite in argument.

Version no.: 1 Page 18 of 46

Page 19: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 18:Valorile primite prin eveniment de la clasa "PumpSensorValue" sunt afisate inMessageBox

Stop 15 Martie 2010

4.4 Prezentarea datelor in DataGrid

Scopul final al proiectului e sa prezentam datele nu prin mesaje, ci folosind un grid care sa se populeze cudatele venite de la senzori.Proiectul "DataPresentation" este de tip "Windows Form Application", deci in cadrul lui avem acces lacontroalele vizuale din ToolBox. Putem gasi la sectiunea "Data" un control de vizualizare de tip grid:

Figura 19: Controlul DataGridView din ToolBox

Version no.: 1 Page 19 of 46

Page 20: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Selectam acest control si facem drag-and-drop in fereastra principala a proiectului. El va fi instantiatautomat in functia "InitializeComponents" a formei, noi trebuie doar sa-i setam proprietatile in stilul dorit. Darin primul rand trebuie setate numele gridului si "DataSource", adica sursa de unde gridul isi va lua datele casa le afiseze:

Figura 20:Setarea sursei de date pentru gridul de afisare

Se pune numele "dgSensorValueList" iar pentru DataSource se merge pe butonul de rulare in jos si sealege din fereastra aparuta linkul "Add project data source..". Se alege apoi data source de tip Object underegasim toate clasele definite de noi si care pot juca rolul de sursa pentru grid. Din namespace-ul"SensorInput" alegem clasa "SensorBase" drept sursa pentru grid.Odata selectata sursa, VS-ul creeaza automat un obiect de legatura intre grid si clasa sursa. Acest obiecteste de tipul "BindingSource" si apare automat in partea de jos a ferestrei de design. Daca ne uitam infunctia "InitializeComponents" putem gasi codul scris in mod automat pentru legarea gridului laBindingSource si BindingSource la SensorBase:

Se creeaza un obiect de tipul BindingSource:this.sensorBaseBindingSource = new Forms.BindingSource(this.components);

Se alege SensorBase ca DataSource pentru acest BindingSource:this.sensorBaseBindingSource.DataSource = typeof(SensorInput.SensorBase);

Se ataseaza BindingSource la datagrid:this.dgSensorValueList.DataSource = this.sensorBaseBindingSource;

Dupa aceasta bindare gridul va avea coloanele setate dupa proprietatile publice din SensorBase. Se poatemodifica modul de prezentare a datelor (coloanele afisate, fontul dorit, headere si multe altele) din fereastrade proprietati a gridului.

Dupa setarea tuturor proprietatilor pentru datagrid se ruleaza programul si se observa ca gridul apare infereastra cu toate coloanele stabilite in design. Si totusi, nu are nici o linie de date inclusa.Si asta deoarececlasa "SensorBase" este doar o definitie, ea nu are efectiv date in ea. Se populeaza gridul cu date numai daca ii dam ca sursa o lista de obiecte de tip SensorBase, fiecare obiectavand valorile date de clasa PumpSensorValues.

Version no.: 1 Page 20 of 46

Page 21: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 21: Popularea listei sensorValueList si setarea ei ca DataSource pentru grid

Definim in clasa DataPresentation o lista de tipul SensorBase

List<SensorBase> sensorValueList = new List<SensorBase>();

Iar in handler-ul de tratare a evenimentului primit de la sensor, comentam linia cu MessageBox-ul (nu maivreau sa afisez informatia prin mesaj) si inserez linia:

this.BeginInvoke(new VoidFunctionDelegate(BindDataGridToListOfValues));

4.4.1 Controalele de tip GUI nu sunt thread-safe

In loc de linia cu BeginInvoke, as fi vrut sa apelez direct functia BindDataGridToListOfValues(). Dar dacafacem asa ceva, apare o eroare foarte interesanta la executie:

Figura 22: Eroare: un alt thread acceseaza datagridul

Care este problema de fapt? Eroare spune ca un alt thread (fir de executie) decat cel care l-a creat,acceseaza datagridul. Ce sunt thread-urile sau firele de executie. Se stie ca Windows-ul poate lansa maimulte aplicatii simultan. Pentru ficare aplicatie cand e pornita, Windows-ul creeaza un nou fir de executie

Version no.: 1 Page 21 of 46

Page 22: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

pentru acea aplicatie si-i da drumul sa ruleze. In acest fel se aduna mai multe fire de executie, toate cerandtimp microprocesor pentru executie. In functie de prioritatea lor, Windows-ul le acorda la fiecare un timpmicroprocesor in care acel thread sa-si faca treaba. Deci microprocesorul porneste un thread, apoi ilopreste si da microprocesorul la alt thread, apoi la altul, apoi se intoarce iar la primul si tot asa.

Acelasi multithreading se intampla si-n aplicatia noastra. Clasa PumpSensorValues are o functie de pornirea ceasului:

public void StartPumping() { timerBase.Start(); }

Aceasta functie aparent nevinovata de fapt creeaza un alt thread in care va lucra ceasul. Ceasul este unobiect ce lucreaza in background si nu are sens sa ocupe din threadul curent de executie. El isi deschideun thread separat de unde trimite din cand in cand evenimente de tip "Time_Elapsed".

Tehnica programarii de tip multithreading este foarte utila atunci cand trebuie indeplinite taskuri mariconsumatoare de timp: download-area unui fisier mare de pe internet, accesul la o baza de date,deschiderea de fisiere mari, etc. Daca aceste taskuri s-ar executa in acelasi fir de executie cu cel pricipal ceraspunde de interfata cu utilizatorul, atunci aceasta interfata ar fi inghetata (froozen) pe timpul rularii lor.Adica programul nu mai raspunde la nici o actiune a utilizatorului deoarece este captiv in acel task lung. Deaceea se prefera ca acel task se porneasca pe un alt thread, iar threadul principal sa ramana activ pentru araspunde la comenzile utilizatorului, si cand threadul secundar se termina, sa trimita un eveniment catrethreadul principal.

Cam asa lucreaza si Timer-ul, el ruleaza pe un thread secundar de unde trimite evenimente catre threadulnostru principal: cel ce afiseaza fereastra si raspunde la butoane. Toate bune si frumoase pana candthreadul secundar arunca un eveniment, acesta este prins intr-o functie si acea functie vrea sa accesezedatagrid-ul (sau orice alt control vizual din fereastra). In acel moment apare eroarea descrisa mai sus,deoarece controalele vizuale nu sunt "thread-safe", adica nu lucreaza bine pe mai multe fire de executie.Nici nu au cum daca ne gandim ca threadurile lucreaza intretesut, adica se intrerup unul pe altul in modpermanent. Si se pot intampla situatii cand un thread modifica culoarea la un control in verde de exemplu sieste intrerupt in acest timp de un alt thread care modifica in rosu. Ce culoare ar trebui sa aiba controlul lasfarsit? De aceea s-a hotarat ca toate controalele vizuale nu lucreaza multithreading si nu accepta controluldecat de la threadul care l-a instantiat.

Pentru a sari in threadul principal din threadul secundar, apelam functia BeginInvoke, care pune in coadade mesaje al threadului principal functia ce trebuie executata. Este aceeasi functie"BindDataGridToListOfValues", dar prin apelul BeginInvoke eu o trimit spre executie thread-uluiprincipal. Fiind executata de thread-ul principal, se paote umbla la controlul datagrid si sa-i setamDataSource pe lista de valori obtinuta in celalalt thread.

private void BindDataGridToListOfValues() { dgSensorValueList.DataSource = null; dgSensorValueList.DataSource = sensorValueList; }

Deci, la fiecare eveniment primit de la celalalt thread, eveniment ce vine dupa el cu o noua valoare desenzor, noi adaugam in lista acea valoare si reconectam lista la datagrid pentru afisare.

Version no.: 1 Page 22 of 46

Page 23: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 23: Fereastra principala de prezentare a datelor cu datagrid-ul legat la lista de valori

4.5 Controale vizuale: CheckBox, TextBox. Clasa Dictionary

In constructorul clasei de prezentare a datelor se starteaza o singura instanta a clasei PumpSensorValues.In realitate sunt mai multi pacienti conectati la aplicatia de monitorizare ce ruleaza pe calculatoruldoctorului. In afara de valorile de masurare, gridul de vizualizare a datelor trebuie sa afiseze si codulpacientului de la care provin datele.In acest scop se modifica clasa "SensorBase" sa contina si codul pacientului pentru care trimite valorile.

Version no.: 1 Page 23 of 46

Page 24: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 24: Adaugarea codului de pacient in clasa cu valorile senzorilor

Constructorul clasei "PumpSensorValues" se modifica pentru a primi ca parametri codul pacientului pentrucare trimite valori, cat si intervalul de timp intre doua masurari succesive.

Figura 25: Patient code trebuie adaugat si in clasa PumpSensorValues

Iar cand se trimite evenimentul "newSensorValueEvent" acesta trebuie sa contina in argument si codul depacient:

Figura 26: Evenimentul "newSensorValueEvent" include si codul de pacient

Ramane ca si in gridul de prezentare a datelor sa se adauge o coloana de afisare a codului de pacient. Sedeschide fereastra de proprietati a gridului si sa da click pe Add pentru a adauga noua coloana"PatientCode" definita in clasa "SensorBase" folosita ca sursa de date pentru grid:

Version no.: 1 Page 24 of 46

Page 25: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 27: Adaugarea coloanei PatientCode in datagrid

Acum ca avem si codul de pacient in SensorBase, putem construi o interfata ce ne permite sa startam unpacient nou, sau sa oprim trimiterea datelor de la un pacient deja pornit.Vom introduce in fereastra "DataPresentation" doua butoane "Start Pumping" si "Stop Pumping" care sastarteze un pacient selectat dintr-un comboBox. De asemenea, intervaulul de timp dintre doua masuratorisuccesive se citeste dintr-un textBox:

Figura 28: Fereastra DataPresentation cu butoanele de startare si oprire a monitorizarii

CheckBox-ul de selectare a pacientilor are ca DataSource o enumerare unde se introduc toate codurile de pacienti.

Version no.: 1 Page 25 of 46

Page 26: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 29: Enumerarea ce include codurile de pacienti

Iar aceasta enumerare se pune ca sursa de date pentru checkBox:

Figura 30: Atasarea unei enumerari la un CheckBox

Butonul "Start Monitoring" trebuie sa porneasca monitorizarea pentru pacientul selectat in checkBox avand ca interval de timp valoarea din textBox-ul aferent:

Figura 31: Codul aferent butonului "Start Monitoring"

Functia trebuie sa verifice ca checkBox-ul are un pacient selectat si ca textBox-ul pentru numarul desecunde contine un numar intreg valid. De exemplu, daca utilizatorul introduce numarul "12ax", acest textnu poate fi convertit la un intreg si trebuie afisat mesj de eroare. Prinderea acestei situatii se face printr-oconstructie de tip try-catch.

Se scrie o functie "startPumping" care primeste ca parametri codul pacientului si numarul de secunde intredoua masurari pentru acel pacient si aceasta functie trebuie sa starteze monitorizarea pentru acel pacient:

Version no.: 1 Page 26 of 46

Page 27: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 32: Functia StartPumping cu parametrii cod pacient si perioada de timp

Problema care apare in momentul cand se lucreaza cu mai multi pacienti este ca putem din greseala sapornim acelasi pacient de mai multe ori si am primi de la acelasi cod de pacient seturi de date diferite.Putem indrepta aceasta greseala daca construim un dictionar care sa includa toti pacientii activi impreunacu obiectul "SensorBase" atasat.

Clasa "Dictionary" lucreaza ca o colectie de perechi de obiecte, primul obiect din pereche avandsemnificatia unei kei. Perechile de obiecte se adauaga in dictionar foarte simplu prin comanda Add si apoisa poate cauta o anumita pereche daca se da keia pentru acea pereche:

Se defineste o noua instanta a clasei Dictionary pentru perechea de obiecte: PatientCodeEnum siPumpSensorValues:

Dictionary<PatientCodeEnum, PumpSensorValues> dictPatientPump = new Dictionary<PatientCodeEnum, PumpSensorValues>();

Dupa startarea unui nou pacient, perechea pacient-pumpSensorValue se adauga in dictionar:dictPatientPump.Add(patCodeEnum, sensorValuesPump);

Inainte de startare se cauta in dictionar daca nu cumva acest pacient este deja activ. In cazadevarat se da mesaj de eroare:if (dictPatientPump.ContainsKey(patCodeEnum))

{ MessageBox.Show("The selected patient has the pump already started"); return; }

Functia aferenta butonului "Stop Monitoring" trebuie sa opreasca monitorizarea pentru acel pacient si apoisa elimine pacientul din dictionarul cu pacientii activi:

Version no.: 1 Page 27 of 46

Page 28: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 33: Oprirea monitorizarii pentru un pacient si eliminarea lui din dictionarul pacientilor activi

In sfarsit am obtinut ceva... un grid care se incarca periodic cu o noua linie ce afiseaza ultima masuratoareobtinuta de la senzori aferenti unui pacient activ, putem de asemenea starta sau stopa monitorizarea unuipacient cu o perioada de timp programabila.

Totusi treaba nu e gata, mai trebuie lucrat la interfata (butoane de filtrare a informatiei, alarme, etc) cat sialte taskuri ramase in aer:

Salvarea datelor intr-o baza de date (ce ne facem daca doctorul vrea sa vada valorile deacum o saptamana si noi am pierdut lista de valori?)

Comunicare TCP/IP intre PumpSensorValues si datagrid (sa nu uitam ca in principiu,pacientul sta acasa si PumpSensorValues ruleaza la pacient acasa, pe candDataPresentation ruleaza la doctor in cabinet, deci pe calculatoare diferite).

Si altele...

Version no.: 1 Page 28 of 46

Page 29: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Version no.: 1 Page 29 of 46

Page 30: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

5 Salvarea informatiilor in baza de date

Pana in acest moment, datele ce vin de la pacient sunt puse intr-o lista dinamica si afisate in datagrid. Dacase inchide aplicatia, atunci toate informatiile primite se vor pierde, doctorul nu are nici o posibilitate saanalizeze o informatie din trecut. Nu este suficient sa afisam datele, trebuie ca aceste date sa fie salvate peun suport permanent si sa poata fi restaurate la un moment dat, daca doctorul doreste sa faca o examinarea pacientului si are nevoie de istoricul datelor de masurare.

In acest capitol vom rezolva problema salvarii datelor intr-o baza de date si problema inversa, de citire ainformatiilor din baza pentru perioade de timp stabilite si un pacient dat. Totusi, nu vom folosi o baza de date foarte mare gen Oracle, deoarece nu sunt foarte multe date si foartecomplexe de salvat si nu are sens sa ocupam memoria cu motorul bazei de date. Mai ales ca, e posibil caaceasta aplicatie sa ruleze pe un telefon mobil ce are constrangeri evidente de memorie disponibila. Deaceea vom utiliza SQLite, o baza de date mult mai mica si fara sa necesite instalari complexe. AcestSQLite este un simplu DLL care se salveaza odata cu aplicatia si poate fi apelat in orice moment pentruaccesarea bazei de date ce este formata dintr-un singur fisier.

5.1 Crearea bazei de date SQLite

Mai intai se instaleaza SQLite database prin rularea aplicatiei “SQLite-1.0.62.0-setup.exe”. Se deschideapoi “sqliteadmin.exe”, aplicatia cu care administram baza de date SQLite si se creeaza o noua baza dedate (butonul ).

Figura 34: Crearea bazei de date “PatientData” in SQLite Administrator

Se deschide apoi baza de date si se creeaza un table pentru salvarea datelor ce vin de la pacient:

Version no.: 1 Page 30 of 46

Page 31: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 35: Crearea tabelului “PatientData” pentru salvarea datelor ce vin de la pacienti

In afara de cele patru campuri de valori ce vin de la pacient se mai adauga un camp numit id de tip varcharsi care va fi coloana de tip “primary key” pentru acest tabel. Tabelul se mai poate crea si prin instructiuneaSQL specifica:

CREATE TABLE [PatientData] ([id] VARCHAR(16) PRIMARY KEY NULL,[patient_code] VARCHAR(10) NULL,[sensor_type] VARCHAR(20) NULL,[timestamp] DATE NULL,[value] NUMERIC NULL)

5.2 Data Acquisition Layer : interfata intre baza de date si aplicatia GUI

Nu este indicat sa se acceseze direct baza de date din functiile ce apartin de clasa GUI. Conexiunea labaza de date, functiile SQL, trebuie sa fie create pe un nivel intermediar, de sine statator si care va fi apelatde clasa superioara de tip GUI pentru orice accesare a bazei de date.

Adaugam un nou proiect la solutie, dar de data aceasta de tip “Class Library” (deci un simplu fisier DLL,fara nici o interfata cu utilizatorul), pe care-l denumim “DataStore”:

Version no.: 1 Page 31 of 46

Page 32: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 36: Adaugarea proiectului “DataStore” de tip “Class Library” la solutie

Dorim sa utilizam SQLite ca baza de date pentru acest proiect, deci trebuie adaugate la proiect referinteleSystem.Data si System.Data.SQLite. In cadrul proiectului vom utiliza si clasa “SensorBase” definita inproiectul “SensorInput”, deci va trebui adaugata si aceasta referinta (add reference, sectiunea “Projects”).

5.2.1 Definirea string-ului de conectare la baza de date in pagina de proprietati a proiectului

String-ul de conectare la baza de date (unde se gaseste baza de date si modul de conectare la ea)reprezinta o informatie care este accesata ori de cate ori trebuie sa lucram cu baza de date. De aceea,acesta informatie se salveaza o singura data in pagina de proprietati a proiectului si va fi citita din pagina oride cate ori este nevoie de ea. Pagina de proprietati este o modalitate de gestionare simpla si rapida aresurselor comune proiectului. O resursa (cum este acest string de conectare) se salveaza o singura datain pagina de proprietati si apoi va fi vizibila pe tot cuprinsul proiectului.

Se deschide pagina de proprietati a proiectului si se defineste la sectiunea “Settings” stringul de conectarela baza de date SQLite:

Version no.: 1 Page 32 of 46

Page 33: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 37: Definirea string-ului de conectare la baza de date SQLite in pagina de proprietati aproiectului

Se pune numele proprietatii “ConnStringSQLite”, se alege la “Type” tipul resursei “Connection String”, iar la

“value” se da click pe butonul pentru a defini conexiunea cu ajutorul Wizard-ului. Se deschide Wizard-ulsi se selecteaza la “DataSource” driver-ul “.NET Framework Data Provider for SQLite”, iar la “DataBase” semerge cu butonul “Browse” si se selecteaza fisierul creat pentru baza de date. La sfarsit se poate face si untest de verificare daca conexiunea este setata corect (butonul “test Connection”).

5.3 Clasa de interfata cu baza de date

5.3.1 Salvarea informatiilor in baza de date

Odata ce am definit conexiunea cu baza de date, putem construi functia de adaugare a unei valori demasurare (o instanta de SensorBase) in baza de date. Adaugam o noua clasa la proiectul “DataStore”numita “DAL_PatientData” :

Version no.: 1 Page 33 of 46

Page 34: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 38: Functia de inserare a unei valori de masurare in baza de date

Etapele ce trebuie parcurse pentru salvarea valorilor de masurare in baza de date sunt urmatoarele:

Se defineste un obiect de tipul “SQLiteConnection” cu care putem sa ne conectam la baza de date.String-ul de conectare se citeste din fisierul de proprietati ale proiectului(Properties.Settings.Default.ConnStringSQLite).

Se defineste obiectul SQLiteCommand cu care vom executa instructiunea SQL de inserare in bazade date

Setam instructiunea SQL ce trebuie executata de SQLiteCommand Setam parametrii ce trebuie trimisi la SQLiteCommand cu valorile de masurare primite prin obiectul

sensorData. Deschidem conexiunea la baza de date si executam comanda SQL Inchidem conexiunea la baza de date

Trebuie observat ca accesul la baza de date s-a facut prin constructia try-catch-finally pentru a ne asiguraca tratam eroarea aparuta in cazul cand baza de date nu raspunde.

Tot ce mai ramane de facut este de a apela functia de salvare in baza de date in momentul cand proiectul“DataPresentation” primeste o noua valoare de masurare prin evenimentul “newSensorValueEvent”:

Version no.: 1 Page 34 of 46

Page 35: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 39: Tratarea evenimentului “newSensorValueEvent”: salvare in baza si afisare in datagrid

Nu trebuie sa uitam sa adaugam referinta la proiectul “DataStore” in cadrul proiectului “DataPresentation”.

In sfarsit, putem verifica daca totul lucreaza OK, pornim aplicatia cu F5, startam pacientul 0101 si dupacatva timp ne uitam in baza de date cu ajutorul programului SQLite Adminstrator. Deschidem o fereastra decomenzi SQL si introducem comanda SQL de vizualizare a tabelei “PatientData”:

Figura 40: Comanda SQL de vizualizare a datelor din tabela PatientData

Executam comanda SQL cu tasta F9 si ar trebui sa observam datele salvate in tabela de aplicatia “HealthMonitor”:

Figura 41: Vizualizarea datelor din baza in SQLite Administrator

Version no.: 1 Page 35 of 46

Page 36: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

5.3.2 Citirea informatiilor din baza de date

Stocarea informatiilor in baza de date permite doctorului in orice moment sa analizeze datele din trecutpentru un pacient dat. In primul rand trebuie creata o sectiune de filtrare a datelor unde doctorul sa-siselecteze pacientul pe care vrea sa-l analizeze si intervalul de timp pentru care vrea sa vada datele.

Se adauga un fereastra “DataPresentation” un control de tip GroupBox ce contine doua controle de filtrare: comboBox pentru selectia pacientului monthCalendar ce selecteaza ziua pentru care se doreste a fi vizualizate datele buton pentru efectuarea filtrarii: “Display Selected data”.

Figura 42: Fereastra DataPresentation dupa ce s-a adaugat sectiunea de filtrare

Dupa selectia pacientului si a zilei de vizualizare, utilizatorul face click pe butonul “Display Data” si in acelmoment trebuie citita din baza de date lista tuturor masuratorile salvate in acea zi pentru respectivulpacient.

In acest scop, clasa “DAL_PatientData” trebuie sa fie completata cu o functie de citire a informatiilor dinbaza de date:

Version no.: 1 Page 36 of 46

Page 37: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 43: Functia de citire din baza de date a datelor de masurare pentru un pacient si o zi stabilita

Functia de citire din baza de date are urmatoarea structura: se creeaza o noua lista “sensorValueList” unde vor fi salvate informatiilor gasite in baza se defineste un nou obiect de tip SQLiteConnection si un obiect SQLiteCommand se scrie instructiunea SQL de selectie din baza de date si se ataseaza obiectului SQLiteCommand se adauga parametrii de filtrare: patient_code, minTime si maxTime se deschide un SQLiteReader in care se salveaza toate liniile aduse din baza de date de fraza

select (reader = cmd.ExecuteReader();). Se parcurge reader-ul linie cu linie, se face conversia datelor aduse de fraza select la tipul

SensorBase si se adauga noul item la lista de valori. La sfarsit se inchide conexiunea, reader-ul si se returneaza lista de valori.

Totusi avem o mica problema: proiectul “DataStore” nu cunoaste tipul de date “PatientCodeEnum” cu caretrebuie sa lucreze functia “GetData” pentru ca aceasta enumerare este definita in proiectul

Version no.: 1 Page 37 of 46

Page 38: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

“DataPresentation”. Ar trebui ca proiectul “DataPresentation” sa fie adaugat in lista de referinte a proiectului“DataStore”. Dar acest lucru nu este posibil pentru ca, deja proiectul “DataStore” este referinta la proiectul“DataPresentation” si ar rezulta o referinta circulara. Nu este posibil ca un proiect P1 se fie referinta la altproiect P2 si in acelasi timp proiectul P2 sa fie referinta la P1. Deci nu se poate sa un proiect sa fie tata laalt proiect si in acelasi timp sa fie fie si copil la acelasi proiect.Din acest motiv, se creeaza un nou proiect numit “CommonReferences” care va contine doar un fisier undevor fi definite toate tipurile de obiecte comune celorlalte proiecte. Acest proiect va fi adaugat ca referinta latoate proiectele ce lucreaza cu acele tipuri de date. Evident, ca acest proiect nu trebuie sa faca referire lanici un alt proiect din solutie.

Figura 44: Proiectul “CommonReferences” contine toate definitiile particulare ale tipurilor de date

Am mutat definitiile “PatientCodeEnum” si “SensorType” in “CommonReferences” astfel incat acestea sa fievizibile in toata solutia fara probleme de referinta circulara.

Tot ce mai ramane pentru vizualizarea datelor din baza de date e sa implementam codul pentru butonul“Display selected Data”:

Version no.: 1 Page 38 of 46

Page 39: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 45: Afisarea valorilor din baza de date

Afisarea se face in acelasi datagrid, trebuie doar sa schimbam proprietatea “dataSource” pentru acest gridpe lista de valori adusa de functia DAL_PatientData.GetData(). Totusi, folosind acelasi grid pentru afisareaambelor tipuri de valori, atat cele primite online de la patientii activi, cat si cele aduse din baza de date,trebuie definita a variabila logica care sa specifice tipul de date ce trebuie vizualizate:

private bool displayTheReceivingData = true;

Iar aceasta variabila va fi setata corespunzator pe cele doua butoane “Display Selected Data” si “DisplayReceived Data”:

Figura 46: Functia handler pentru butonul “Display Received Data”

Version no.: 1 Page 39 of 46

Page 40: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

6 Transmiterea datelor intre aplicatii. Socket TCP/IP

Pana acum, atat proiectul care producea date (SensorInput), cat si proiectul care consuma datele(DataPresentation), ruleaza sub aceeasi solutie, in acelasi calculator si atunci evenimentele trimise defurnizorul de date pot fi receptionate de consumatorul de date. Si totusi, realitatea sta un pic altfel: furnizorulde date ruleaza la pacient acasa, iar receptorul ruleaza la medic in cabinet. Intre ele exista o legaturainternet sau intranet prin care trebuie transmise datele.

In acest capitol vom analiza modul de conectare a celor doua aplicatii printro legatura de tip Socket TCP/IP.Tehnologia Socket lucreaza pe arhitectura client-server. Se deschide un server TCP/IP care ruleaza unlistener ce asculta la un port dat cererile de conectare de la diversi clienti TCP/IP din retea. Cand soseste ocerere de conectare, se deschide un canal de comunicatii intre cele doua aplicatii prin care pot fi transferatedate in ambele sensuri.

Se modifica proiectul "DataPresentation" prin adaugarea unor radio butoane care sa selecteze modul detransmitere a datelor:

prin TCP/IP la un calculator dat de o adresa IP direct la calculatorul curent

Figura 47: Proiectul Data Presentation cu posibilitatea de a alege canalul de comunicare a datelor

Version no.: 1 Page 40 of 46

Page 41: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Pentru a realiza o comunicatie TCP/IP trebuie construite urmatoarele obiecte: TcpClient ce primeste datele de masurare de la sensor, le impacheteaza intr-un format text si le

transmite la server TcpServer care deschide listenerul si accepta cererile de conexiune sosite de la client, primeste

textul de la client, il despacheteaza in format SensorBase si-l trimite mai departe la"DataPresentation"

Evenimentul prin care serverul sa transmita la interfata DataPresentation valorile primite de la client

Se creeaza un nou proiect in cadrul solutiei numit "TCPCommunication", proiect ce include doua clase:TCPCommClient si TCPCommServer:

Figura 48:Solutia "HealthMonitor" cu toate proiectele componente

6.1 Obiectul TCPCommClient

In continuare se prezinta clasa "TCPCommClient" cu urmatoarele functionalitati:

Primeste data de tip "SensorBase" pentru a fi trimisa la server Porneste un nou fir de execuie (thread) care sa se ocupe separat de deschiderea conexiunii si

trimiterea datelor Impachetarea clasei "SensorBase" intr-un text dupa un anumit format standard Inchiderea firelor de executie ramase suspendate daca serverul refuza sa raspunda la cererea de

dialogSa luam aceste functii pe rand:

Version no.: 1 Page 41 of 46

Page 42: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

6.1.1 Impachetarea datelor pentru transmisie

Clasa TCPCommClient afiseaza urmatoarele functii publice: Constructorul clasei

Figura 49: Constructorii clasei TCPCommClient

Se observa ca constructorul implicit al clasei a fost declarat privat astfel incat sa nu poata fi posibila oinstantiere a clasei de forma "new TCPCommClient()", adica sa se creeze o instanta fara a da si adresa IPa serverului la care trebuie sa se conecteze clientul pentru a trimite date. Singurul constructor disponibil dinexterior este cel ce primeste ca parametru adresa IP a serverului. In acest fel ne asiguram ca toti clientiiTCP creati vor avea setata adresa IP a serverului cu care trebuie sa dialogheze.

"SendSignalData" ce primeste cele patru valori din clasa SensorBase in scopul trimiterii lor catreserver.

Version no.: 1 Page 42 of 46

Page 43: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 50: Functiile de primire si impachetare a datelor ce trebuie trimise la server

Functia ce primeste datele pentru transmisie apeleaza mai intai functia de impachetare a datelor in formattext, dupa care face apel catre functia de trimitere a textului. Este mai avantajoasa trimiterea sub forma detext a datelor pentru ca pot fi procesate cu ajutorul functiilor de tip string si in plus, sender-ul si receiver-ulpot avea structuri de date diferite, totul e sa se stabileasca formatul de impachetare care sa fie respectat deambele parti.S-a decis asupra urmatorului format:

- Simbolul "#" semnifica inceputul si sfarsitul mesajului- Simbolul "," separa campurile de date specifice clasei "SensorBase"- Ordinea de impachetare este urmatoarea: SensorType, TimeStamp,

PatientCode, Value.Concatenarea acestor string-uri in mesajul de trimis se face cu jutorul functiei "Append" din cadrul clasei"StringBuilder".

6.1.2 Crearea unui nou fir de executie pentru fiecare dialog cu serverul

Functia ce trimite efectiv mesajul text catre server este listata in continuare:

Figura 51: Startarea unui nou thread pentru trimiterea datelor

Crearea unui nou fir de executie pentru trimiterea textului la server se face prin apelul constructorului clasei"Thread" din namespace-ul "using System.Threading;":

Se creeaza instanta clasei "Thread":Thread newThread = new Thread(new ParameterizedThreadStart(SendSignalTextNewThread));

Se adauga thread-ul format in lista de thread-uri a clasei

Version no.: 1 Page 43 of 46

Page 44: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

myThreadList.Add(newThread);

se porneste noul fir de executie avand ca parametru textul ce trebuie trimis la server: newThread.Start(signalText);

Dar mai intai se inchid toate thread-urile ramase in suspensie de la vechile incercari de dialog cu serverul.Daca serverul nu raspunde in timp util, aceste fire de executie raman suspendate si ocupa memoria in modabuziv. Daca sunt mii de date de trimis si in tot acest timp serverul nu raspunde, sunt mii de thread-uriramase in suspensie. De aceea trebuie facuta curatenie din cand in cand:

Figura 52: Inchiderea firelor de executie inactive

Se creeaza o noua lista de thread-uri in care sa vor salva toate firele de executie care sunt inca active.Daca thread-ul nu este activ se inchide prin apelul functiei Abort(). La sfarsit lista de thread-uri a clasei va fiinitializata cu noua lista, fiind alcatuita numai din firele de executie active.

6.1.3 Trimiterea datelor catre server

Trimiterea efectiva a textului catre server se face in functia ce ruleaza in firul de executie nou creat. Aceatsfunctie urmeaza urmatorii pasi:

se obtine o instanta a clasei de biblioteca TcpClient cu parametrii: _serverIP si _port; se obtine un obiect de tip "NetworkStream" pe care-l returneaza acest TcpClient. Acest stream

poate trimite octetii unul dupa altul pe canalul deschis intre client si server despachetam mesajul de tip text intr-un sir de octeti ce pot fi trimisi pe canalul de comunicatie:

ASCIIEncoding encoding = new ASCIIEncoding(); byte[] buffer = encoding.GetBytes(signalText);

Version no.: 1 Page 44 of 46

Page 45: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Apelam functia stream.Write pentru a trimite datele. Aceasta functie "Write" lucreaza ca si cum amscrie intr-un fisier, problemele hardware de low level de transmitere efective a datelor fiindtransparente pentru noi ca utilizatori.

Figura 53: Dialogul cu serverul

6.1.4 Functia Dispose inchide firele de executie suspendate

Daca utilizatorul inchide brusc aplicatia (cand inca sunt active fire de executie ce trimit date catre server)atunci trebuie apelata o functie pe evenimentul "DataPresentation_FormClosing" (deci cand fereastraeste pe punctul de a se inchide) care sa inchida toate resursele aferente acestei aplicatii.

Figura 54: Tratarea evenimentului "FormClosing" in clasa "DataPresentation"

Functia apelata la inchiderea aplicatiei pentru inchiderea tuturor firelor de executie aferente clientului este"Dispose()". Pentru a nu uita ca trebuie sa scrim aceasta functie, am mostenit clasa "TCPCommClient" dininterfata "Idisposable" si astfel, in mod automat VS-ul te obliga sa implementezi functia Dispose():

Version no.: 1 Page 45 of 46

Page 46: Programare Visual Studio - docshare04.docshare.tipsdocshare04.docshare.tips/files/31736/317364954.pdf · 5 SALVAREA INFORMATIILOR IN BAZA DE DATE ... 6.1.3 Trimiterea datelor catre

Programare Visual Studio .NET - LABORATOR Project no. PVS 2008 Product name: Programare Visual Studio Date: Feb - 2010

Document no. Version no.: 0.1 CR no.: Author: Lucian Nita

Figura 55: Componentele interne ale clasei "TCPCommClient"

Figura 56: Inchiderea firelor de executie la terminarea programului

6.2 Obicetul TCPCommServer

Acest obiect trebuie sa deschida un listener care sa receptioneze cererile de conectare de la clienti, sadeschida canalele de comunicatie, sa receptioneze mesajele, sa despacheteze aceste mesaje si sa trimitavalorile primite mai departe la "DataPresentation".

Version no.: 1 Page 46 of 46