Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Pomoc oko threda

[es] :: .NET :: Pomoc oko threda

[ Pregleda: 3011 | Odgovora: 13 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Ognjen_NS
NoviSad

Član broj: 76177
Poruke: 82
*.dialup.neobee.net.



Profil

icon Pomoc oko threda23.05.2006. u 14:18 - pre 218 meseci
Kreirao sam win aplikaciju koja je povezana preko web servisa sa bazom. Pored glavne forme, kreirao sam "formicu" molim sacekajte...., Kada preko neke metode "pitam bazu", pokrenem tread za tu formicu da se prikaze korisniku Molim sacekajte na sledeci nacin:
Code:

 public void PrikaziStudenteIFajlove(DataGridView gridviewIspitZaSiF, DataGridView gridviewIspitFajlovi)
        {
            //kreiramo  thred
            Thread workerThread = new Thread(new ThreadStart(ShowSacekajte));
            workerThread.Start();
           
            int ID_Ispit = 0;
            //obezbedjujem ID_Ispita jer mi treba za metod koji vraca IspitFajlovi tabelu
            foreach (DataGridViewRow row in gridviewIspitZaSiF.Rows)
            {
                if (row.Selected == true)
                {
                    ID_Ispit = Convert.ToInt32(row.Cells[0].Value.ToString());
                }
            }

            //sakrijemo potrebne kolone
            gridviewIspitFajlovi.DataSource = VratiIspitFajloviTabelu(ID_Ispit);
            
            //ubijemo tred
            workerThread.Abort();

public void ShowSacekajte()
        {
            Molim.ShowDialog();
        }


E sada, ovo radi ali nekad mi javi porukom da thread nije napusten.... Da li neko moze da mi kaze kako da ovo odradim da se ta poruka nikad ne javi znaci da bude safe....(nikako da skontam onaj background worker, moze li bez njega?)

U pitanju je VS 2005
Hvala
 
Odgovor na temu

Oliver Klaćik
Vice President, Thunder Road Software
Inc.
Stara Pazova

Član broj: 34059
Poruke: 242
80.93.231.*

Sajt: www.thunderroadsoftware.c..


Profil

icon Re: Pomoc oko threda24.05.2006. u 05:49 - pre 218 meseci
Najviše mrzim kada se greška nekada javi, a nekada ne... Onda je ludilo hvatati uzrok...

Anyway, moj savet ti je da UI uvek držiš na glavnom thread-u, a da novi thread koristiš za data access.
Oliver 'FAQ' Klaćik
 
Odgovor na temu

erkan
Sarajevo

Član broj: 12339
Poruke: 267
*.hermes.si.

ICQ: 238530669


Profil

icon Re: Pomoc oko threda24.05.2006. u 08:53 - pre 218 meseci
Mozda zato sto nisi zatvorio formu 'molim sacekajte'
prije nego sto si ubio thread!?
Samo se budala saplice na kamen iza sebe.
 
Odgovor na temu

Ognjen_NS
NoviSad

Član broj: 76177
Poruke: 82
*.telekom.yu.



Profil

icon Re: Pomoc oko threda25.05.2006. u 17:16 - pre 218 meseci
Na zatvaranje forme sam totalno zaboravio:) ali nije to reshilo problem. I dalje mi ponekad baci exception, retko ali ipak baci
 
Odgovor na temu

erkan
Sarajevo

Član broj: 12339
Poruke: 267
*.hermes.si.

ICQ: 238530669


Profil

icon Re: Pomoc oko threda26.05.2006. u 15:05 - pre 218 meseci
Jos jedan mali osvrt samo...
Malo sam pozaboravio ali, zasto taj thread kreiras uvijek
iz pocetka, ja bih radije postavio da je thread globalni (da ga tako nazovem)
pa kad udjes u f-ju, prvo ispitas da li je aktivan a onda ga 'startas' ako nije...
Tako imas vecu kontrolu nad tredom
Samo se budala saplice na kamen iza sebe.
 
Odgovor na temu

Ognjen_NS
NoviSad

Član broj: 76177
Poruke: 82
*.telekom.yu.



Profil

icon Re: Pomoc oko threda27.05.2006. u 17:00 - pre 218 meseci
Ne znam, ali ovo izgleda stvarno nesto nije dobro
Jel ima neko ko je radio nesto slichno u VS2005, pa da pastuje code? Ili ako ima neko link neki za slican problem?
Sta god uradio exception se javi i ja sam glup da to reshim
 
Odgovor na temu

lopkiju

Član broj: 81874
Poruke: 31
212.200.5.*

Sajt: mojprevoz.com


Profil

icon Re: Pomoc oko threda31.05.2006. u 21:58 - pre 217 meseci
Radio sam sa thredovima, ali nikada ih nisam unistavao na kraju (mozda sam trebao).

Elem, mozes da handlujes gresku pa ti nece doaadjivati, ali tako ne resavas problem, a slozio bih se sa ekranom da kreiras thred globalni za tu klasu.
 
Odgovor na temu

ebug
BiH,Sarajevo

Član broj: 70579
Poruke: 8
85.158.35.*



Profil

icon Re: Pomoc oko threda26.06.2006. u 20:21 - pre 217 meseci
Nadam se da jos provjeravas post ili da je aktuelan.

Razlog Thred break-a moze biti a pretpostavljam da vjerovatno i jeste, - thread na kome se pravi forma(Molim) i thread na kojem se ona izvrsava nisu isti. Mislim da moras pozvati Molim.Close() na ispravnom Thread-u,tj. ako, InvokeRequired vrati true, Molim.Invoke(delegat na metodu u kojoj zelis Molim.Close() ). Poslije ovoga mislim da je sasvim "legalno" uraditi abort radnik-Threda koji je sve ovo napravio.

Ja sam koristio Molim.Invoke() jer ne zelim vratiti kontrolu glavnom Thread-u dok se Molim-forma ne zatvori. Molim.BeginInvoke(.......) bi koristio u slucaju kada zelis samo poslati poruku (npr. Molim.Close() ) Thread-u na kojem se Molim izvrsava i odmah nakon toga bi vratio kontrolu glavnom Thread-u a Molim forma bi se zatvorila kada zavrsi sa nekim svojim operacijama (ako ih ima). U ovom slucaju bi morao paziti kada pozivas workerThread.Abort() jer ne zelis dozvoliti da se thread ugasi prije nego oslobodi(ugasi) Molim formu.

Code:

        //na nivou glavne Form klase sam napravio Molim formu
        Form Molim;

        public void PrikaziStudenteIFajlove()
        { 
            //prikaz ID-a thread na zaglavlju glavne forme
            this.Text = "Thread ID = "+Thread.CurrentThread.ManagedThreadId.ToString();
           
            //kreiramo  thred            
            Thread workerThread = new Thread(new ThreadStart(ShowSacekajte));
            workerThread.Start();

           //Neka operacija na glavnom thread-u npr. filovanje grida
            Thread.Sleep(2000);

            //provjera za zatvranje forme molim
            if (Molim.InvokeRequired)
            {
                Molim.Invoke(new MethodInvoker(MojaMetoda));
            }          

            workerThread.Abort();
            
            //npr. cekanje na glavni thread da ugasi workerThread
            while (workerThread.IsAlive) { }
            this.Text="workerThread IsAlive = " + workerThread.IsAlive.ToString();
        }

        public void ShowSacekajte()
        {
            Molim=new Form();           

            //Prikaz ID-a thred-a na formi Molim
            Molim.Text = "Thread ID = " + Thread.CurrentThread.ManagedThreadId.ToString();
              
            Molim.ShowDialog();           
        }

        private void MojaMetoda()
        {
            Molim.Close();           
        }  


Naravno, postoje i druga rijesenja za ovaj problem i best practice rjesenje bi bilo da svoj kod za fill grida prebacis na drugi thread jer je to operacija koja je zahtijevna, a da glavni thread oslobodis za druge operacije (korisnik moze raditi nesto drugo, itd...) + mozda je elegantnije korisnika obavijestiti nekim progressbar-om ili nekom drugom kontrolom o ucitavanju grida ili statusom aplikacije.

Volio bih da sam bio od pomoci i nadam se da ce ovo popraviti bug sa thread-om koji imas.
Ako ti ne bude mrsko postaj da li je sada ok.

sretno.

[Ovu poruku je menjao ebug dana 26.06.2006. u 22:19 GMT+1]
 
Odgovor na temu

Ognjen_NS
NoviSad

Član broj: 76177
Poruke: 82
212.200.218.*



Profil

icon Re: Pomoc oko threda27.06.2006. u 10:57 - pre 217 meseci
nisam radio na taj nachin. Koristio sam background worker u klasi Molim. Evo odprilike nesto ovako:

U klasi molim:
Code:

public MolimSacekajte(Rad rad)
        {
            this.rad= rad;
            InitializeComponent();
            backgroundWorker1.RunWorkerAsync();
        }

        //metod workera "DoWork"
        private void Odradi(object sender, DoWorkEventArgs e)
        {
            rad.Svasta();//ova metoda u klasi Rad proverava da li je Invoke potreban i puni grid
        }
        
        //metod workera DOne
        private void Zavrshi(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Close();
        }


ovako to pozivam u klasi rad:
Code:

MolimSacekajte molim = new MolimSacekajte(this);
molim.ShowDialog();


Code:

       //kreiram delegata
        private delegate void MojDelegat();

        //pozivam metod za punjenje
        public void Svasta()
        {
            if (this.InvokeRequired)
                this.Invoke(new MojDelegat(
                        this.UradiSveUZavisnostiOdButtona));

            else
            {
                this.UradiSveUZavisnostiOdButtona();
            }
        }



Ovo radi, ne "zapucava" se program nigde, jedina stvar je sto nece da mi prikaze progress bar (marque). U stvari on prikaze molim formu, ali je progress bar prazan (nekad se prikazu plavi blokovi, nekada ne):) Ne znam ovo tvoje, sada zurim ali popodne cu bas da testiram, hvala u svakom slucaju.
 
Odgovor na temu

ebug
BiH,Sarajevo

Član broj: 70579
Poruke: 8
85.158.32.*



Profil

icon Re: Pomoc oko threda27.06.2006. u 12:52 - pre 217 meseci
Evo samo kratko prije nego udjemo u teoriju.


Mislim da bi sa ovim kodom opet mogao imati problema. Gavni razlog za to bi mogao biti "neopredjeljivanje" za to kome ces dati (kome thread-u) da radi operaciju koja je vremenski zahtijevna (grid operacije koje imas,itd....).
Cini mi se da ovaj novi kod koji si poslao pomalo i sustinski razlikuje od posta koji je prvi bio.

Ako se ne varam, sada si se odlucio da formu "Rad" kompletnu proslijedjujes novoj formi (pretpostavljam zbog reference na isti objekat) "Molim" pa da zatim u formi "Molim" pokreces backgroundworker i sa njim odradjujes operaciju koja je zahtijevna.
Za to vrijeme ti je samo modalna forma("Molim") aktivna tj. samo ona ima neku interakciju sa korisnikom. Medjutim ti samo sto zapocnes ovu operaciju na backgroundWorker-u ( Odradi ()) vracas kontrolu nazad MainThredu na kojem se nalaze i glavna forma i modalna forma (to je ovaj delegat sa this.Invoke(.......)) i tu ponovo nesto radis na glavnom thread-u. Tako da glavni thread i pomocni thread se "svadjaju" oko nekih stvari (mozda progressbar).

-Pretpostavljam da se progres bar nalazi na formi Molim ili .......treba mi malo vise pojasnjenja......

Uglavnom pravilo je slijedece: Svaka klasa koja nalslijedjuje iz klase ......Control ima samo 4 Thread safe metode tj. samo te 4 se mogu pozvati sa bilo kog' thread-a.
To su: Invoke(...), BeginInvoke(...), EndInvoke(...), CreateGraphics(...) + property InvokeRequired, ako bilo sta drugo, sto je vezano za neku kontrolu, pozoves sa thred-a koji nije napravio tu kontrolu rizikujes thread bug tj. bug koji ce ozbiljno narusiti "integritet" aplikacije. Upravo je problem sa thread-ovima to sto su ovi bug-ovi suptilni tj. neke ce debuger primijetiti, neke nece, neki ce se manifestovati cudnim ponasanjem aplikacije a neki ce je "srusiti", tako da trebas biti jako pazljiv pri rukovanju. :)



[Ovu poruku je menjao ebug dana 27.06.2006. u 14:05 GMT+1]

p.s. Evo sad sam stigao neki mali projekat da napravim da cijela prica ne bude apstrakcija :), pa mi samo reci da li je ovo efekat koji si trazio. Saljem sada samo debug.rar folder iz projekta a ako je to to, saljem i projekat.

[Ovu poruku je menjao ebug dana 27.06.2006. u 16:21 GMT+1]
Prikačeni fajlovi
 
Odgovor na temu

Ognjen_NS
NoviSad

Član broj: 76177
Poruke: 82
*.adsl.sezampro.yu.



Profil

icon Re: Pomoc oko threda28.06.2006. u 22:41 - pre 217 meseci
To je to:)
Ako moze posalji mi code. E hvala ti bash. Chitao sam ja o thredovima, i stvarno mi neke stvari nisu bile jasne. Sada mi je mnogo jasnije. Bitno je reci da bas nesto i nisam imao vremena da se toliko bakcem sa tim, ali ovih dana imam vremena pa cu dublje zaci u tematiku istih. Jos jednom ti hvala
 
Odgovor na temu

ebug
BiH,Sarajevo

Član broj: 70579
Poruke: 8
85.158.32.*



Profil

icon Re: Pomoc oko threda29.06.2006. u 12:25 - pre 217 meseci
.....drago mi je sto sam mogao biti od pomoci. :)
Samo cu malo napisati o kodu o kojem smo pricali.

Pri pisanju ovog koda ja sam pokusao sto blize tvom problemu kodirati tj. pristupio sam problemu na nacin na koji si i ti to uradio. Tako da moj kod sadrzi takodjer backgroundworker Thread na "Molim Sacekajte" formi te, Invoke i BeginInvoke metode na "Rad" formi. Za ove dvije metode se moze reci, uz dovoljno "pjesnicke slobode" :), da predstavljaju u odredjenom smislu dio "Inner working-sa" backgroundWorker komponente.
Tako da, koristenje obje varijante, backgroundWorker + BeginInvoke ili Invoke, predstavlja u odredjenom smislu dupliranje tj. bakcgroundWorker bi bio sasvim dovoljan, a uz to i puno sigurniji (govoreci jezikom OOP jer se drzi odredjenih paradigmi istog) za posao koji je trebao da se uradi.

Znaci, u predhodnom postu kada sam rekao da je problem "neopredjeljenost" kojem ces thread-u dati da radi posao, na ovaj problem "dupliranja" sam mislio, a ujedno ako pogledas svoj kod vidjeces da je metoda Svasta() proglasena kao public. Razumijem da si to uradio da bi dobio pristup "Rad" klasi ali moze se desiti situacija kada vanjski kod koji Instancira klasu "Rad", pokrene metodu Svasta() na Main thread-u. Najblaze sto se moze desiti je gomila hidden bug-ova ili da se aplikacija "zaledi" ili bilo sta drugo......jer je ova metoda namijenjena radu sa nekog drugog thread-a. :)
U krajnjoj instanci to znaci da je kod koji ti saljem, tehnicki "dovoljno dobar" samo dok si ti(onaj koji razumije sta kod radi) taj koji ga koristi. Ako bi tvoj kod trebao da odrzava neki drugi programer poslije tebe ili ce ga neko drugi nekada upgrade-ovati, mogao bi imati problema sa razumijevanjem zasto je nesto uradjeno na ovaj ili onaj nacin.
U projektu sam se potrudio komentarisati stvari koje radim i reci nesto malo o tome zasto ih radim pa se nadam ce pomoci.

Kada, u toku istrazivanja thread-ova (generalno govoreci), budes imao tzv. "aha-aaaaa" momente :), ne bi bilo lose da ih postas jer su thread-ovi, skoro uvijek, nedovoljno obradjena tema. :)

p.s. Projekat je pisan za FrameWork 2.0 i koristen je VS 2005 a jezik je C#.


Prikačeni fajlovi
 
Odgovor na temu

Ognjen_NS
NoviSad

Član broj: 76177
Poruke: 82
*.adsl.sezampro.yu.



Profil

icon Re: Pomoc oko threda30.06.2006. u 12:08 - pre 216 meseci
E ovako:)

POgledao sam tvoj code i da ti se jos jednom zahvalim na njemu. Moja pitanja su:

1. Tebi je metod svasta takodje deklarisan kao public. A rekao si da to bas i nije dobro?(Blokiranje app u nekim trenutcima itd a to bash i ne bih voleo da se desi). Naime, shto se tiche koriscenja samo bacground workera, bez invoke i begin invoke, koliko sam chitao u msdn-u, trebalo bi da se metod (u nashem sluchaju svasta) pozima u eventu Done, sto znaci u metodi background workera gde mi zatvaramo formu "molim". Oni kazu da se tako "nece buniti" ako kontroli pristupamo iz drugog treda?? Sto mi bas i nije jasno:)

ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxmclictl/html/138f38b6-1099-4fd5-910c-390b41cbad35.htm

2. Takodje se isto desava u metodu svsta. Razlika je u Thread.Sleep(100), ja ga nisam imao i sto pozivas delegat sa BeginInvoke a ja sa Invoke.

Pa ako moze malo pojasnjenje. Ovo ostalo je sve jasno. Shto se tiche ProgressBara, da li mozda znas da li mogu nekako da povecavam blokove ako se nesto upisuje u bazu (ne znam koliko ce da traje)? Mislim lako je proveriti koliko recorda ima upisano u tabeli baze pa na osnovu toga povecavati progres bar, tj. odrediti granicu.

PS: Postavljanjem Thread.Sleep(300), ProgressBar radi:)

Hvala josh jednom


[Ovu poruku je menjao Ognjen_NS dana 30.06.2006. u 13:28 GMT+1]
 
Odgovor na temu

ebug
BiH,Sarajevo

Član broj: 70579
Poruke: 8
85.158.35.*



Profil

icon Re: Pomoc oko threda30.06.2006. u 16:48 - pre 216 meseci
OK.
Haj'mo redom.

1.
Tako je......Ostavio sam metodu svasta(...) da ti pokazem na koji nacin bi se ona mogla pozivati u konkretnom kodu a da se ne "sudara" sa drugim threadovima i da kod ispravno radi. Tu metodu bi trebalo prihvatiti kao "los" nacin za postizanje zeljenog rezultata. Sto znaci, treba je promijeniti ili potpuno izbaciti. Ako bi je izbacili, onda moramo naci druga+tehnicki ispravna logicka rjesenja za dati problem a to sada zavisi od tebe(programera) da nadjes odgovarajuci nacin.
Sa tehnicke strane postoje razliciti nacini da se neko koristenje Thread-a ucini da bude thread safe. I to je upravo ovo o cemu prica ovaj primjer na MSDN-u koji si poslao. Oni su takodjer upotrijebili 2 nacina da urade istu stvar. Jedan nacin je pomocu novog Thread-a a drugi pomocu background worker-a. I jedan i drugi nacin mogu djelovati sami za sebe tj. nisu zavisni. Ovaj sto se radi preko novog Thread-a se upravo "naslanja" na ono pravilo da sve sto je napravljeno naslijedjivanjem iz ...Control klase ima samo 4 thread-safe metode i jedan property. Dok se za backgroundWorker moze reci, opet uz dosta pjesnicke slobode :), da takvo pravilo "zna-sam-po-sebi" i da ga u svom radu primjenjuje. Ako pogledas backgroundWorker vidjeces da on daje 3 eventa i 2(ovoj prici bitna, a ima ih jos) property-ja. Da bi osposobio da rade sva 3 eventa property "WorkerReportsProgress" mora biti postavljen na "true". Sta se tada desava: Sav posao se obavlja na relaciji prvi event - drugi event. Sto znaci, pokrenes svoj backgroundWorker a on pokrece 1. event. Tu ti primjenjujes neku svoju logiku.....Ali pazljivo jer sve sto ovdje mozes da radis mora biti thread-safe jer se ovaj posao odvija na drugom Thread-u. Znaci, ako u ovom threadu koristis bilo koju kontrolu ili bilo sta sto naslijedjuje iz control klase a koja nije napravljena na ovom threadu dobices thread bug.Da bi ovo sprijecio imas na raspolaganju 2.Event koji pokreces naredbom bakgroundWorker.ReportProgress(...). To je event gdje se sve odvija na threadu koji je napravio backgroundWorker-a a u nasem slucaju i sve kotrole. Znaci, u ovom eventu je sasvim "legalno" mijenjati kontrole tj. Update-ovati progressbar,grid, textBox itd....bilo sta. Ovaj postupak(1-2) se odvija stalno dok god backgroundWorker thread ne zavrsi posao tj. u nasem slucaj dok traje "while.." petlja. Zatim, worker thread javlja da je zavrsio posao a tebi kao korisniku to daje do znanja u 3.Eventu i tu se proces zavrsava. Takodjer, 3.Event se odvija na istom thread-u gdje su u nasem slucaju i sve kontrole pa sta god radio sa nasim kontrolama u ovom eventu je thread-safe. Ovaj drugi property ti omogucava da prekines posao backgroundWorker-thread-a i tada bi posao presao iz 1. eventa u 3.event uz eventualni prolazak kroz event 2 i tu bi bio kraj rada thread-a.
Samo radi pojasnjenja:
1.Event je "backgroundWorker1_DoWork(.....)"
2.Event je "backgroundWorker1_ProgressChanged(...)"
3.Event je "backgroundWorker1_RunWorkerCompleted(...)"

2.
Evo jedan link koji odlicno objasnjava kako rade Invoke(...) i BeginInvoke(...) pa probaj naci vezu izmedju njega i backgroudWorker-a. Poslije njega bi stvari trebale biti jasnije. Thread.Sleep(...) u kodu je samo radi pokaza laganog punjenja grida ti se slobodno mozes rijesiti toga ili prilagodjavati svojim zahtjevima.

http://www.codeproject.com/csharp/begininvoke.asp

3.
Progressbar prilagodjavaj po svojoj zelji - glavna stvar je da ga "punis" na ispravnom thread-u a implementaciju mozes prilagodjavati kako zelis. Izazovi "punjenja" progressbar-a su stalni i naici ces na razlicita rjesenja u praxi (Timer-i,Thread-ovi,sekvence,....itd).

Oko thread-ova ima jos dosta toga sto se veze za implemetaciju ovih gore stvari ali to bi sada na ovoliko detalja bilo i previse. Izvinjavam se ako je post predugacak ali nadam se da ce ti neke stvari, ako nista drugo onda, malo pribliziti i da ga nije bilo naporno citati.

[Ovu poruku je menjao ebug dana 30.06.2006. u 20:51 GMT+1]
 
Odgovor na temu

[es] :: .NET :: Pomoc oko threda

[ Pregleda: 3011 | Odgovora: 13 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.