Avatar billede joshin Nybegynder
08. maj 2012 - 19:44 Der er 4 kommentarer og
1 løsning

web application threading

Hej,
Jeg har følgende udfordring i en web application:
Den afvikles i tre trin.
1 bruger oploader en fil
Filen kontroleres
Filens indhold bearbejdes, og resultatet lageres (i en database)

Problemet er at siden timer ud.
Jeg vil gerne lade bearbejdningen foregå i en seperat tråd, som så skriver en status i en global variabel.
På siden skal der så være et update panel, med en timer der spørger på status, og hvis status er færdig, så vises resultatet.

Er der nogen der ligger inde med noget kode, eller links til tutorials som kan pege mig i den rigtige retningen?
Jeg kan ikke få threading til at virke overhoved.
Avatar billede arne_v Ekspert
08. maj 2012 - 20:01 #1
Du burde kunne starte en traad, men det er et forkert design - web apps boer ikke starte traade.

Du boer lade den langvarige processing ske uden for ASP.NET f.eks. i en Windows Service.
Avatar billede keysersoze Guru
08. maj 2012 - 22:29 #2
Præcis hvad er det der timer ud? Upload? kontrol? bearbejdning? og hvad bearbejdes?
Avatar billede joshin Nybegynder
09. maj 2012 - 17:16 #3
@arne_v
du har ret, men det skal køre på et hosted webhotel, så jeg kan ikke installere noget.

@keysersoze
Den timer ud i bearbejdningen. Det er en csv fil der bruges til at oprette poster på et eksisterende site (i en kalender), den kan nå 6-7 liner/poster ad gangen.
Avatar billede arne_v Ekspert
13. maj 2012 - 01:38 #4
Der er mange problemer med at starte en traad.

Hvad goer du naar app poolen recycles?

Du skal sikre dig at alt der laves er atomic.
Avatar billede montago Praktikant
09. juni 2012 - 18:09 #5
Det er faktisk ikke så svært:

1. du skal lave et Javasciprt som ticker 1 gang pr sekund som poller din side. brug POST ikke GET!

2. jeg regner med du selv kan lave resten af front-enden...

Koden herunder gør alt du beder om, mangler kun din logik.
//--------------------------------------------

public partial class MinTrådSide : System.Web.UI.Page
{
    static Thread WorkerThread;
    static Queue<ThreadInfo> ToBeStarted = new Queue<ThreadInfo>();
    static List<ThreadInfo> ActiveWorkers = new List<ThreadInfo>();
    static ThreadInfo LastWorker;

    protected void Page_Init(object sender, EventArgs e)
    {
        Response.Expires = -1;

        if (TDLinkWorker == null)
        {
            TDLinkWorker = new Thread(new ThreadStart(Worker_DoWork));
            TDLinkWorker.IsBackground = true;
            TDLinkWorker.Start();
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request["GetWorkerStatus"] != null)
        {
            Response.Clear();
            Response.Write(WorkState());
            Response.Flush();
            Response.End();
            return;
        }
    }

    private string WorkState()
    {
        if (ActiveWorkers.Count > 0 || LastWorker != null)
        {
            var ti = ActiveWorkers.FirstOrDefault();

            if (ti == null && LastWorker != null)
                ti = LastWorker;

            string html = "<ul>";

            double splat = ti.TimeSpend.TotalSeconds / (double)(ti.AtRow);
            double left = splat * (ti.MaxRows - ti.AtRow);
            TimeSpan timeleft = new TimeSpan(0, 0, (int)left);

            html += "<li>" + ToBeStarted.Count + " job i kø</li>";
            html += "<li>" + (int)(((double)ti.AtRow / (double)ti.MaxRows) * 100) + "% færdig med nuværende job.</li>";
            html += "<li>tid tilbage: " + String.Format("{0:00}:{1:00}:{2:00}", timeleft.Hours, timeleft.Minutes, timeleft.Seconds) + "</li>";
            html += "<li>" + (ti.MaxRows - ti.AtRow) + " linier tilbage</li>";
            html += "<li>" + ti.Fejl + " fejl</li>";
            html += "<li>" + ti.Oprettede + " oprettede</li>";
            html += "<li>" + ti.Rettede + " rettede</li>";

            return html;
        }
        else
        {
            return "<b>Klar...</b>";
        }
    }

    //KNAP PÅ DIN SIDE SOM INDSÆTTER NOGET ARBEJDE I TRÅD-KØEN
    protected void btnStartWorker_Click(object sender, EventArgs e)
    {
        //OPRET DE LINIER SOM SKAL ARBEJDES
        var txtarr = tbPair.Text.Replace("\r", "").Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); ;

        //OPRET ET OBJEKT SOM SKAL SÆTTES I KØ
        ThreadInfo ti = new ThreadInfo
        {
            Lines = txtarr,
            MaxRows = txtarr.Length,
            FejlLinier = "",

            OPTION0 = DropDown.SelectedValue.toInt(),
            OPTION1 = (DropDown2.SelectedValue == "OPTION555"),
            OPTION2 = CheckBox.Checked,
        };

        ToBeStarted.Enqueue(ti);
    }

    void Worker_DoWork()
    {
        while (true)
        {
            if (ToBeStarted.Count > 0)
            {
                ThreadInfo TI = ToBeStarted.Dequeue();
                ActiveWorkers.Add(TI);

                //DET ER ULTRA VIGTIGT AT LAVE EN NY DATACONTEXT SOM BRUGES I TRÅDEN !!
                MyDataContext db2 = new MyDataContext();

                //STOPWATCH SOM BRUGES TIL AT BEREGNE RESTERENDE TID
                Stopwatch watch = new Stopwatch();
                watch.Start();

                var data = from l in TI.Lines
                          where l.Trim() != ""
                          let arr = l.Split(';')
                          let DATA0 = arr[0]
                          let DATA1 = arr[1]
                          let DATA2 = arr[2]
                          select new { DATA0, DATA1, DATA1 };

                foreach (var item in data)
                {
                    //TÆL DATA-LINIE OP TIL STATISTIK
                    TI.AtRow++;


                    if (db2.FOOBAR.Any(a => A.DATA0 == item.DATA0))
                    {
                        //TÆL FEJL OP HVIS LINIEN IKKE SKAL BEHANDLES ELLER LÆGGES DATABASEN ELLER HVIS ANDEN FEJL
                        TI.Fejl++;
                    }
                    else
                    {
                        //LINIEN SKAL BEHANDLES ELLER GEMMES I DATABASEN

                        var rec = db2.FOOBAR.FirstOrDefault(a => a.DATA0 == item.DATA0 && a.DATA1 == item.DATA1);

                        if (rec == null)
                        {
                            db2.FOOBAR.InsertOnSubmit(new FOOBAR
                            {
                                DATA0 = item.DATA0,
                                DATA1 = item.DATA1,
                                DATA2 = item.DATA2,
                            });
                            //TÆL OPRETTEDE LINIER OP
                            TI.Oprettede++;
                        }
                        else
                        {
                            //EN LINIE SKAL RETTES
                            rec.DATA2 = item.DATA2;

                            //TÆL RETTEDE LINIER OP.
                            TI.Rettede++;
                        }

                        //GEM 200 LINIER AF GANGEN SÅ DATABASEN OG TRÅDEN IKKE LÅSER FOR MEGET
                        if (TI.AtRow % 200 == 0)
                            db2.SubmitChanges();

                        if (TI.AtRow % 20 == 0)
                        {
                            //SLEEP ENGANG IMELLEM FOR AT GØRE TRÅDEN LAV PRIORITET
                            Thread.Sleep(10);
                            //GEM TIDS STATUS TIL STATISTIK
                            TI.TimeSpend = watch.Elapsed;
                        }
                    }
                }

                //GEM LINIER SOM IKKE ER MODULUS 200
                db2.SubmitChanges();

                //SÆT SIDSTE WORKER TIL STATUS UDPRINT
                LastWorker = TI;
                ActiveWorkers.Remove(TI);
            }

            //SLEEP SÅ LÆNGE TRÅDEN IKKE HAR NOGET AT ARBEJDE MED
            Thread.Sleep(500);
        }
    }

    class ThreadInfo
    {
        //TRÅD INFO TIL POLL-VISNING
        public int Fejl { get; set; }
        public int Oprettede { get; set; }
        public int Rettede { get; set; }
        public string FejlLinier { get; set; }

        public int AtRow { get; set; }
        public TimeSpan TimeSpend { get; set; }
        public int MaxRows { get; set; }

        //TRÅD DATA TIL BEHANDLING (TILFØJ ELLER SLET PROPS EFTER BEHOV)
        //LINIER FRA CSV SOM SKAL BEHANDLES
        public string[] Lines { get; set; }
        //INDSTILLINGSMULIGHEDER FRA INPUT PÅ SIDEN
        public int OPTION0 { get; set; }
        public bool OPTION1 { get; set; }
        public bool OPTION2 { get; set; }

    }
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester