vlakna

C,C++,C#

Moderátori: psichac, Moderátori

wizing
Nový člen
Nový člen
Príspevky: 95
Dátum registrácie: 21 Sep 2017, 09:09
Bydlisko: Žilina
Vek: 40

vlakna

Príspevok od používateľa wizing » 23 Apr 2021, 11:33

Zdravím Vás.
pracujem na takomto kóde vo Visual Studio v C#

Kód: Vybrať všetko

        private void btnPosli_Click(object sender, EventArgs e)
        {          
            zapisuj();  
            citac citac = new citac();
            Thread vlakno = new Thread(citac.precitaj);
            vlakno.Start();       
        }     
po stlačení tlačidla Posli mi zapíše dáta. Potrebujem však aby mi za behu programu nestuále čítalo v cykle
funkciu citaj(); a z nej mi ich vypisovalo na richtextbox.
Vytvoril som si na to nové vlákno, ktoré ale nepozná môj richtextbox pretože nebol v ňom vytvorený ale ho využíva hlavné vlákno programu.

Kód: Vybrať všetko

        class citac
        {
            public void precitaj()
            {
                while (vlaknoCitac == true)
                {
                    citaj();
                    ...................posli na ritchtextbox
                }
            }
        }
Je možné nejakým spôsobom vysvetliť novému vláknu že precitane dáta má odosielať na ten vytvorený ritchtextbox v hlavnom vlákne? google mi dal radu že si mám vytvoriť delegata .... lenže problém je že nenašiel som vhodnú stranku kde sa problému venovali natoľko aby som tomu pochopil ..... bol by mi niekto ochotný poradiť?
Veľmi pekne ďakujem.
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: vlakna

Príspevok od používateľa Radus » 23 Apr 2021, 12:02

No neviem či som pochopil správne, ale mal by si si vytrvoriť event, ten by si spustil z vlákna čítača. V hlavnom vlákne by sa prihlásil na daný event a pozavolaní eventu by ten v hlavnom vlákne niečo zapísal do rtb.
ALE - dostaneš hlášku že sa pokušaš zmeniť niečo z iného vlákna v akom bolo vytvorené (cross threat detected bla bla...). Ale aj to sa dá ošetriť pomocu control invoke...

Takže, napíšeš si Event s omáčkou (v triede čítač):

Kód: Vybrať všetko

 	public class WriteTextEventArgs : EventArgs
        {
            public WriteTextEventArgs(string _text)
            {
                Text = _text;
            }

            public string Text { get; }
        }
        public delegate void WriteTextHandler(object sender, WriteTextEventArgs e);
        public event WriteTextHandler WriteTextHandlerEvent;
        
        protected void CallWriteTextEvent(WriteTextEventArgs e)
        {
            if (WriteTextHandlerEvent != null) WriteTextHandlerEvent(this, e);
        }
vo vlákne čítača event zavoláš:

Kód: Vybrať všetko

...
WriteTextEventArgs ev = new WriteTextEventArgs("Text na vypisanie...");
CallWriteTextEvent(ev);
...
v hlavnom vlákne sa potom prihlásiš delegáta k triede u teba je to čítač, u mňa je to trieda lProc (inštancia z processingClass)...

Kód: Vybrať všetko

lProc.WriteTextHandlerEvent += TextWriteEvent;
vytvoríš funkciu ktorá sa bude volať:

Kód: Vybrať všetko

        private void TextWriteEvent(object sender, ProcesingClass.WriteTextEventArgs e)
        {
            throw new NotImplementedException();
        }
a do nej doplníš výpis do RTB, + trieda na ošetrnie výnimky ktorú som spomínal... u mňa je to bt_jobDel, u teba to bude nejaký richTextBox...

Kód: Vybrať všetko

  private void TextWriteEvent(object sender, ProcesingClass.WriteTextEventArgs e)
        {
            FormControlHelper.ControlInvike(bt_jobDel, () => bt_jobDel.Text = e.Text);
        }
a pomocná funkcia pre to križovanie vlákien:

Kód: Vybrať všetko

public class FormControlHelper
    {
        delegate void UniversalVoidDelegate();

        /// <summary>
        /// Call form controll action from different thread
        /// </summary>
        public static void ControlInvike(Control control, System.Action function)
        {
            if (control.IsDisposed || control.Disposing)
                return;

            if (control.InvokeRequired)
            {
                control.Invoke(new UniversalVoidDelegate(() => ControlInvike(control, function)));
                return;
            }
            function();
        }
    }
Takéto riešenie používam ja... a pijem pivo :)
0
Naposledy upravil/-a Radus v 23 Apr 2021, 12:20, upravené celkom 5 krát.

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2562
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: vlakna

Príspevok od používateľa maskrtnik01 » 23 Apr 2021, 12:12

Asi najčistejšie riešenie by bol BackgroundWorker. Ten zabezpečí vykonávanie úlohy v samostatnom vlákne, aj zobrazenie stavu v UI vlákne.

Priamo k otázke. Keďže už nie ste v triede Formu, samozrejme že nepozná RichTextBox. Môžete ho ale prepašovať cez parameter worker funkcie. Dopadne to tak, ako spomenul Radus, program spadne lebo iba UI vlákno môže narábať s controlmi.
0

wizing
Nový člen
Nový člen
Príspevky: 95
Dátum registrácie: 21 Sep 2017, 09:09
Bydlisko: Žilina
Vek: 40

Re: vlakna

Príspevok od používateľa wizing » 23 Apr 2021, 12:29

chalani vďaka .... cez víkend si k tomu sadnem a skúsim to takto. Už aj v práci nad tým sedím a lámem si hlavu a robota mi stojí .... som už z toho celkom zúfalý
Veľká vďaka za ten vzorový kód ... poštudujem to podľa neho....
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: vlakna

Príspevok od používateľa Radus » 23 Apr 2021, 12:33

Ešte nezakladaj triedu citač vo funkcii volanej tlačítkom, ale priamo v namespace. Vo funkcii ju možeš inicializovať. A nepomenuvávaj rovnako triedu a inštanciu triedy...a podobne :)
0

wizing
Nový člen
Nový člen
Príspevky: 95
Dátum registrácie: 21 Sep 2017, 09:09
Bydlisko: Žilina
Vek: 40

Re: vlakna

Príspevok od používateľa wizing » 23 Apr 2021, 12:39

keby som niečo podobné pchal do mikrokontroléra tak čítanie vložím do prerušenia a je po probléme ale tu sa to tak spraviť nedá ....
prerobím si to a naštudujem podľa tvojho vzoru ..... ešte raz fakt veľká vďaka som ti nesmierne vďačný....mám sa od čoho odpichnúť...
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: vlakna

Príspevok od používateľa Radus » 23 Apr 2021, 12:42

áno, ja som si tiež písal pre jeden projekt v C# pre simuláciu programu v MCU a musel som preto použiť 3 vlákna...taký je život.
//a v prerušení nahodíš len flag že sa ma spustiť čítanie a ten ošetríš v hlavnom programe, však? ;)
0

wizing
Nový člen
Nový člen
Príspevky: 95
Dátum registrácie: 21 Sep 2017, 09:09
Bydlisko: Žilina
Vek: 40

Re: vlakna

Príspevok od používateľa wizing » 23 Apr 2021, 12:56

áno tak nejak ......
tento program ktorý sa snažím ukuchtiť by mal riešiť taký domáci rodinný chat počas práce s ftp serverom.
text vložím do txt súboru v adresári oboch účastníkov chatu a potrebujem aby program neustále čítal údaje ktoré odosielateľ pošle a zobrazil ich v rtxBoxe. Čo pošle jeden účastník zobrazí hneď obom a naopak.
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: vlakna

Príspevok od používateľa Radus » 23 Apr 2021, 13:13

...nebudem sa vyjadrovať k nápadu...ale možno jednoduchšie by pre teba v takom prípade len si spraviť tlačítko "refresh" a vytvoriť timer ktorý bude priamo, dajme tom raz za 1sek to tlačítko spúšťať, alebo len funkciu...a nebudeš sa musieť naťahovať s vláknami...
0

wizing
Nový člen
Nový člen
Príspevky: 95
Dátum registrácie: 21 Sep 2017, 09:09
Bydlisko: Žilina
Vek: 40

Re: vlakna

Príspevok od používateľa wizing » 23 Apr 2021, 13:30

viem že nápad nie je moc praktický a v dnešnej dobe dosť zbytočný
skôr my išlo o to sa pokúsiť to spraviť ako o to či to prakticky k niečomu bude ..... naučil som sa komunikovať s ftp, naučil som sa na čo slúži vlákno a že vôbec niečo také existuje a zas som o trošku viac pokročil s vedomosťami ohľadom C# a visualu.....a vyplnil som si čas po večeroch .... skôr toto bol účel...
stým timerom ma to vôbec nenapadlo .... skúsim aj túto variantu
0

pocitujlasku
Ultimate člen
Ultimate člen
Príspevky: 6200
Dátum registrácie: 20 Júl 2007, 00:00
Vek: 41

Re: vlakna

Príspevok od používateľa pocitujlasku » 23 Apr 2021, 19:11

vo vlakne vkladaj udaje do concurrentqueue a v hlavnom programe v cykle vyberaj.
vyhoda je, ze ak ti naraz pride vela dat, tak sa nic nedeje, hlavny program si ich bude pekne vyberat
0
Jedním z největších projevů nedůvěry v Boha je hromosvod na kostele.

Používateľov profilový obrázok
Mek
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1271
Dátum registrácie: 15 Okt 2015, 20:49
Bydlisko: Žilina
Vek: 37
Kontaktovať používateľa:

Re: vlakna

Príspevok od používateľa Mek » 24 Apr 2021, 22:51

Samozrejme, vo vlaknach treba pouzivat thread-safe classy a metody na to urcene. Ako bolo spomenute, ConcurrentQueue, potom ConcurrentBag, a na zvysovanie a znizovanie zdielaneho countera ak by bolo treba, Interlocked.Increment a .Decrement.
Suroveho delegata som uz v kode dlho nevidel, asi preto, ze v praci nerobime WinForms aplikacie. Na paralelne spustanie veci pouzivame Parallel.For a metody z classy Task ako Task.Run().
0
... byvaly spravca Hospudky u amplionu, Martinekk-ov brat. Nemam vystudovane elektro, je to len moje hobby. Povolanim som SW inzinier.
Moja databaza suciastok: ELPARTS
Moj velky elektro projekt: MEGA TRANSISTOR CLOCK

pocitujlasku
Ultimate člen
Ultimate člen
Príspevky: 6200
Dátum registrácie: 20 Júl 2007, 00:00
Vek: 41

Re: vlakna

Príspevok od používateľa pocitujlasku » 25 Apr 2021, 08:36

Bag by som nepouzival, v tomto pripade je lepsia queue, nech to ide po poradi.
Este casto vyuzivam dictionary, ale to skor, ak z toho objektu citam. na zapis a spracovanie je idealna queue a velmi jednoducho sa s nou pracuje.
vyhoda je, ze to neblokuje meranie, ak by v hlavnom programe sa nieco zaseklo
0
Jedním z největších projevů nedůvěry v Boha je hromosvod na kostele.

Napísať odpoveď