Sider

Seneste indlæg

Seneste kommentarer

Vis ikke

Nøgleord

Vis ikke

    Tråde og timere

    Her er nogle små eksempler på tråde og timere

    [Denne artikel blev først publiceret på http://todobom.dk/artikler.shtml, men er nu flyttet ind i min blog per 05/05/2010]

    I forbindelse med et projekt på min nuværende arbejdsplads har jeg besluttet at publisere mine overvejelser.

    Opgaven: Udvikl en distribueret client/server-løsning som kan udsende flere hundredetusinde mails om dagen (nope det er ikke spam, men permission marketing - tro mig: jeg afskyr spam og deres ophavsmænd). Selve udsendelsen i sig selv er ikke det store problem. Pt. har vi en ASP3 løsning som fungerer ok, men et ønske om mere kontrol med selve udsendelsen, har drevet udviklingen frem.

    For mig var det en stor mundfuld. Gennem den sidste måneds tid har jeg skullet sætte mig ind i trådprogrammering, .NET Remoting og vende tilbage til OOP - som jeg forlod helt tilbage i 1999, da jeg for alvor begyndte at programmere i ASP. Ja, så det er faktisk syv år siden, jeg sådan rigtig har anvendt OOP.

    Som sagt har vi en kørende løsning som løfter opgaven med at udsende de mange mails. Løsningen baserer sig på ASP3, IIS og IIS'ens SMTP server. Nogen vil sikkert rynke på næsen over det simple setup, men faktisk kører det lynhurtigt. Ihverttilfælde SMTP delen. Derfor vil vi heller ikke ændre på den del.

    Det nye ligger i selve applikationen som fletter de mange emailadresser med nyhedsbrevet. For det første skal applikationen kunne foretage simultane "fletninger" for forskellige nyhedsbreve. For det andet skal applikationen give respons tilbage til en bruger som vil se status på en forsendelse. Via et styrepanel, eller en konsol om man vil, skal en bruger kunne logge sig på applikationen, herefter serveren, og se hvordan en forsendelse står til. Fra styrepanelet skal brugeren kunne stoppe en forsendelse, sætte en forsendelse på pause og udskifte nyhedsbrevet, for derefter at genstarte forsendelsen hvorfra den er kommet.

    I styrepanelet, herefter klienten, skal der være en progressbar som viser hvor langt forsendelsen er kommet. Denne information skal komme fra serveren, som ved hver flettet email skal trigge en event. Denne event skal marshall'es og sendes over et netværk til klienten.

    Opgaven har jeg brudt op i to: en læredel og en udviklingsdel. For det første har jeg skullet høvle mig igennem en anseelig mængde artikler på nettet og MSDN. Artiklerne har været spækket med eksempler som i divergerende grad har kunne bruges i hele eller dele af sit omfang. For det andet har jeg skullet omsætte disse artikler og eksempler til noget brugtbart for min konkrete opgave.

    Efter at have læst artikler og afluret kode, har jeg omsat dem til små praktiske eksempler som behandler en teknologi eller metode i forhold til en specifik problemstilling i projektet. En af dem er asynkron event-handling. Her følger nogle små eksempler:

    Første eksempel demonstrerer hvordan en klasse (Asynkron) som implementerer en asynkron metode (StartAsync) kan kaldes fra en anden klasse (Program). Klassen Program knytter event'en Asynkron.Færdig til en handler.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                List liste = new List();

                Asynkron asynkron1 = new Asynkron(3000, "den første");
                asynkron1.Færdig += new EventHandler(asynkron_Færdig);
                liste.Add(asynkron1);
                asynkron1.StartAsync();

                Asynkron asynkron2 = new Asynkron(8000, "den anden");
                asynkron2.Færdig += new EventHandler(asynkron_Færdig);
                liste.Add(asynkron2);
                asynkron2.StartAsync();

                Console.WriteLine("Tryk på tastaturet for at afslutte");
                Console.ReadKey();
            }

            static void asynkron_Færdig(object sender, EventArgs e)
            {
                Console.WriteLine(((Asynkron)sender).navn + " er endelig færdig");
            }
        }

        class Asynkron
        {
            Thread worker;
            public event EventHandler Færdig;
            public String navn;
            private int hvorLænge;

            public Asynkron(int hvorLænge, String navn)
            {
                this.navn = navn;
                this.hvorLænge = hvorLænge;
            }

            protected void OnFærdig(EventArgs e)
            {
                EventHandler handler = Færdig;
                if (handler != null)
                    handler(this, e);
            }

            public void StartAsync()
            {
                worker = new Thread(Hænger);
                worker.IsBackground = true;
                worker.Start();
            }

            private void Hænger()
            {
                Thread.Sleep(hvorLænge);
                OnFærdig(new EventArgs());
            }
        }
    }

    Eksempel 2

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;

    namespace ConsoleApplication1
    {
        class Program
        {
            static List liste = new List();

            class Tæller
            {
                public int i = 2;
            }

            static Tæller tæller = new Tæller();
            static TimerCallback timerDelegate = new TimerCallback(TimerTick);
            static Timer timer = new Timer(timerDelegate, null, 2000, 2000);

            static void Main(string[] args)
            {
                Console.WriteLine("Tryk på tastaturet for at afslutte");
                Console.ReadKey();
            }

            private static void TimerTick(Object data)
            {
                lock (tæller)
                {
                    if (tæller.i == 0)
                    {
                        Console.Write(".");
                        return;
                    }

                    Asynkron asynkron = new Asynkron(3 * tæller.i, tæller.i.ToString());
                    tæller.i--;
                    asynkron.Færdig += new EventHandler(asynkron_Færdig);
                    liste.Add(asynkron);
                    asynkron.StartAsync();
                }
            }

            static void asynkron_Færdig(object sender, EventArgs e)
            {
                Console.WriteLine(((Asynkron)sender).navn + " er endelig færdig");
            }
        }

        class Asynkron
        {
            Thread worker;

            public event EventHandler Færdig;
            public String navn;
            private int hvorLænge;

            public Asynkron(int hvorLænge, String navn)
            {
                //Console.WriteLine(navn + "");
                this.navn = navn;
                this.hvorLænge = hvorLænge;
            }

            protected void OnFærdig(EventArgs e)
            {
                EventHandler handler = Færdig;

                if (handler != null)
                    handler(this, e);
            }

            public void StartAsync()
            {
                worker = new Thread(Hænger);
                worker.IsBackground = true;
                worker.Start();
            }

            private void Hænger()
            {
                Thread.Sleep(hvorLænge);
                OnFærdig(new EventArgs());
            }
        }
    }


    Posted by todobom on 24. november 2006 10:08
    Permalink | Kommentarer (0) | Post RSSRSS comment feed
    Kommentarerne er lukkede