Programarea in .NET – partea a 14-a Salvare XML si Executare de operatii asincrone in Windows Forms

De ce taskuri asincrone ? In ideea ca , intr-o aplicatie
Windows(si chiar ASP.NET) , operatiile lungi ar trebui sa fie executate de
catre alt thread, urmind ca aplicatia sa poata sa mai afiseze ceva
utilizatorulu in tot acest timp ( fie si un buton pe care scrie „apasa ca sa
intrerupi operatia asta lunga …”). De pilda, in aplicatia noastra, daca avem
mai mult de 100 de Publisher-i si vrem sa ii vedem pe toti – ar trebui
incarcati intr-un nou thread.

 

Ne ocupam mai intii de o aplicatie Windows Forms si pe urma
de ASP.NET

Un thread nu e greu de pornit. Hai sa vedem un exemplu:

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(StartAction));

           
t.Start(“obiect transmis”);

 

 

public void
StartAction(object o)

        {

            string
s = o.ToString();

            System.Threading.Thread.Sleep(5000);

            //executa
actiunea

            //trimite
text

            if
(this.InvokeRequired)

            {

                this.Invoke((MethodInvoker)delegate()

                 {

                     this.Text = s;

                 });

                //sau

                //this.Invoke(new MethodInvoker(evenimentfaraparametri());

                //this.Invoke(new EventHandler(btnDiscounts_Click));

                //this.BeginInvoke(new EventHandler(eveniment cu
parametri));

            }

            else

                this.Text = s;

        }

 

 

Totusi,
exista o problema – dintr-un thread nu se pot accesa DIRECT controale din alt
thread – si de aceea avem instructiunea this. Invoke .Diferenta intre this.Invoke si este this.BeginInvoke aceea ca prima instructiune asteapta rezultatul
actiunii, pe cind a doua doar executa si se intoarce imediat sa execute codul
ramas.

 

De
aceea exista controlul numit BackgroundWorker – care asigura ca , din
evenimentul propriu generat, sa accesezi orice obiect de pe forma. O sa facem
acest lucru pentru salvarea in XML a colectiei de Publisher-i in format XML.

.NET
are o forma usoara de a salva o colectie/clasa in format XML , salvindu-i
proprietatile.

Vom
utiliza modalitatea cea  mai usoara de a
face acest lucru

Marcam
clasa Publisher si clasa colectie ColPublisher cu atributul de   [Serializable]
:

 

[Serializable]

    public
class ColPublisher
: System.Collections.ObjectModel.KeyedCollection<string,Publisher>

 

[Serializable]

    public
class Publisher

 

Acum
o sa facem serializarea obiectului Publisher:

#region Serializer

        /// <summary>

        /// instanta pentru lazy load

        /// </summary>

        private
static XmlSerializer m_Serializer;

        /// <summary>

        /// serializator pentru obiectul publisher

        /// </summary>

        private
static XmlSerializer Serializer

        {

            get

            {

                if (m_Serializer == null)

                    m_Serializer = new XmlSerializer(typeof(Publisher));

 

                return m_Serializer;

            }

        }

 

        /// <summary>

        /// salveaza obiectul ca XML

        /// </summary>

        [XmlIgnore]

        public
string XML

        {

            get

            {

                StringBuilder sb = new
StringBuilder();

                EncodingStringWriter sw = new
EncodingStringWriter(sb, Encoding.Default);

                XmlTextWriter xtw = new XmlTextWriter(sw);

               
Serializer.Serialize(xtw, this);

                return sb.ToString();

 

 

            }

        }

        /// <summary>

        /// recreeeaza un Publisher dintr-un string XML

        /// </summary>

        /// <param
name=”XML”>
string care contine
tot
</param>

        /// <returns></returns>

        public
static Publisher
FromXML(string XML)

        {

            StringReader sr = new StringReader(XML);

            return
Serializer.Deserialize(sr) as Publisher;

        }

        #endregion

 

 

   

Copiem
apoi acelasi cod( cu citeva diferente) si pentru ColPublisher

 

Citeva
comentarii despre cod:

De ce am pus [XmlIgnore] peste  public string XML ? Pentru a nu serializa
si aceasta proprietate, dind astfel nastere la o nedorita recursivitate

Ce e cu clasa EncodingStringWriter
? Este facuta pentru a putea schimba Encoding=ul- daca aveti de exemplu
caractere speciale(diacritice) romanesti/franceze/etc.

De ce metoda FromXML este statica- iar XML este pe
instanta? Asa mi se pare normal – transformarea dintr-un obiect in XML sa
apartina obiectului, iar din XML in obiect nu poate sa apartina unui obiect(
ah, daca as fi putut scrie this = Serializer.Deserialize(sr) as Publisher  !) – ci doar clasei.

Nu se poate face codul mai „generic”? Ba da- una din
deosebiri ar fi ca FromXML ar trebui sa fie pe instanta…

 

 

Haideti acum in proiectul Windows sa serializam o colectie
de Publisher-i.Pe forma frmPublisherList adaugam un buton btnSave, cu textul
Save, dublu click si scriem urmatorul cod:

private void
btnSave_Click(object sender, EventArgs e)

        {

            BookObjects.ColPublisher col =
colPublisherBindingSource.DataSource as
BookObjects.ColPublisher;

            string
strSave = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);

            strSave = Path.Combine(strSave, “pub.xml”);

            File.WriteAllText(strSave,
col.XML);

            System.Diagnostics.Process.Start(strSave);

        }

 

 

Rulati
proiectul, adaugati 2 publisher-i si apasati pe save.

Este
clar ca, daca sunt multi publisher-i, procesul poate deveni prea lung si
blocheaza interfata.

 

Haideti
sa folosim background worker. Il adaugam din toolbox , il redenumim bgSave,
dublu click. Luam codul din btnSave_Click, il adaugam la
si pe urma scriem doar bgSave.RunWorkerAsync();

 

private void
btnSave_Click(object sender, EventArgs e)

        {

            bgSave.RunWorkerAsync();

        }

 

        private
void bgSave_DoWork(object
sender, DoWorkEventArgs e)

        {

            BookObjects.ColPublisher col =
colPublisherBindingSource.DataSource as
BookObjects.ColPublisher;

            string
strSave = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);

            strSave = Path.Combine(strSave, “pub.xml”);

            File.WriteAllText(strSave,
col.XML);

            System.Diagnostics.Process.Start(strSave);

 

        }

 

Data
viitoare  o sa vorbim despre modelul
asincron din ASP.NET.

Leave a Reply

Your email address will not be published. Required fields are marked *