» »

Komunikacija med thread-i

Komunikacija med thread-i

zlatko ::

Imam težavo s komuniciranjem med dvema thread-oma v realnem času. Oba threada sta v istem procesu.

Poizkusil sem že z več rečmi, vendar je težava da ko prvi thread čaka na odgovor drugega, se le-ta ne izvaja. To mi je logično, saj je procesor single-thread. Zato niti logično ne njadem rešitve, kako v realnem času interaktivno komunicirati med thread-i znotraj istega procesa.

Če kdo pozna rešitev, bi mi kratka razlaga zelo pomagala. Hvala.

Vesoljc ::

interaktivno?

a: kje si?
b: tukaj.

tko? ;)

eden izmed načinov je pač nek msg queue/fifo, ki ga ima vsak thread, s tem, da recimo msgji ne bi bili "naslovljeni" ampak bolj raw data. problemi so pa itaq standardni - shared data, kar zahteva locking, kar pa zopet pomeni blocking... zdej je verjetno samo vprašanje razmerja med velikostjo/količino date ter število blockov v časovni enoti. drugače pomoje ne gre. sicer obstajajo atomske operacije, ampak...

lahko poveš bolj natančno, kako komunikacijo želiš?
Abnormal behavior of abnormal brain makes me normal...

Gundolf ::

Kaj pa naj po tvoje dela, medtem ko čaka na odgovor?

No kratka razlaga: Threadi se navidezno izvajajo hkrati, ker jih operacijski sistem tako hitro preklaplja (10ms thread 1, 10ms thread 2, 5ms thread 3, 10ms thread 1, ...). Prekljaplja jih čisto sam od sebe, ne glede na to koliko v danem trenutku procesirajo in pri tem nimaš kaj dosti vpliva (ponavadi lahko nastaviš le prioriteto posameznega threada). Preklaplja jih tudi, ko se threadi sami tako odločijo, ko čakajo na nek dogodek. Recimo da thread 1 čaka, da mu thread 2 zapiše nek rezultat v neko spremenljivko.

Za komunikacijo med threadi imaš na voljo t.i. mutexe, semaforje in condition variables (pa še kaj bi se našlo). Je pa vse odvisno od tega, kakšno komunikacijo rabiš. Boš moral napisati kaj približno si želiš pa boš dobil bolj točen odgovor.

zlatko ::

Evo situacija je naslednja:

Imam Klient aplikacijo in Servis aplikacijo. To je podobno kakor pri MS SQL Server aplikaciji, kjer je SQL Server zagnan kakor servis in pa Enterprise Manager, ki je kot client temu servisu. Med sabo komunicirata preko npr. Pipeinga.

Zdaj pa k mojemu primeru. Tudi pri meni letu v ozadju Servis, ki komunicira s Clientom preko PIPE protokola. V Clientu pa imam dva thread-a. Namreč prvi skrbi za vzopstavitev povezave preko NamedPipe in čaka na kakšno sporočilo z ukazom WaitForMultipleObjects.
Ko iz servisa prileti kakšno sporočilo, ga prestreze prvi thread in ga posreduje drugemu threadu, ki deluje neodvisno od prvega in je pravzaprav glavni thread clienta. Ta sprejme sporočilo od prvega threada in da v dnevnik sporočil ter prikaže na ekran.

Zapovrstje komunikacij pa je naslednje:
- servis pošlje sporočilo clientu in čaka na odgovor
- sporočilo sprejme prvi thread, ga posreduje drugemu threadu in čaka na odgovor
- drugi thread prebere sporočilo in odgovori prvemu threadu
- prvi thread prejme odgovor od drugega in ga posreduje servisu
- ko servis prejme odgovor, nadaljuje z delom

Upam, da je celoten proces dovolj natančno opisan. Torej gre za majhne količine podatkov in za hitro obdelavo le-teh.

Hvala za hiter odziv.

Gundolf ::

Manjka še opis težave ;)

Se pravi thread 2 dela nekaj svojega, ko thread 1 sprejme sporočilo in mu ga želi posredovati. Verjetno je najbolje če thread 2 periodično preverja vsebino neke spremenljivko, v katero thread 1 shrani sporočilo, ko ga dobi. Ali pa, če ima thread 2 nek message queue, da mu thread 1 tja podtakne sporočilo, ko le-to prispe (če je to main thread windows programa, potem ima message queue).

Oziroma - naj thread 1 kar sam ugotovi kaj mora odgovoriti. Dobro premisli, koliko sploh želiš vpletati thread 2 in če to morda ni nepotrebno. Thread 1 bi lahko recimo sam zapisal sporočilo v dnevnik. Znotraj thread 2 bi se to le izpisalo na ekrano, kakor je to pač potrebno. Pa še to bi šlo lahko zelo potihem 'mimo' threada 2, se pravi po običajnih windows kanalih.

Zgodovina sprememb…

  • spremenil: Gundolf ()

zlatko ::

Gundolf
Tudi jaz sem podobno razmišljal, saj je na spletu tudi nekaj examplov na to temo.

Vendar ko thread 1 čaka na odgovor thread-a 2, le-ta ne ve, kdaj je dobil sporočilo, saj z SendMessage ne gre komunicirati med threadi, kolikor mi je znano. S PostMessage je že prepozno. Če bi pa dal v thread 2 Timer, ki bi vsakih toliko časa periodično preverjal vsebino skupne spremenljivke oz. kar strukture, se pa zna narediti, da znotraj enega intervala priletita dve sporočili in tako eno sporočilo izgubimo.

Ne vem pa, kako bi implementiral t.i. message queue. Če prav razumem, thread 1 pošlje windows message v čakalno vrsto messegov thread-a 2 in ta jih jemlje kar po vrsti iz tega seznama. Če je tako, ne vem kako ni kje v kodi bi prebral vsebino iz message queue. Mogoče v WndProc threada 1?

Zgodovina sprememb…

  • spremenil: zlatko ()

BigWhale ::

int i_am_done = 0;

int thread1_run()
{
  do_stuff;
  i_am_done = 1;
  return 0;
}


int thread2_run();
{

  do_other_stuff();
  if (i_am_done)
  {
     he_is_done();
  } else {
    do_something_else();
  }
  do_some_more_stuff();

  return 0;
}



No, nekako tako...
Trotlzihr

zlatko ::

BigWhale
Hvala za psevdokod.

Bi mi kdo hotel posredovati kodo v C-ju, kako bi prebral poslan message iz thread-a 1 v prestrezni rutini okna v threadu 2.
Torej imam TestWndProc proceduro, v kateri lovim določene message tega okna (WM_CREATE, WM_CLOSE, WM_COMMAND ...). Znotraj te procedure bi lahko jemal tudi message iz message queue, kamor bi jih dajal thread 1. Vsaj tako si predstavljam.

zlatko ::

Ali obstaja v C-ju ukaz za procesor, naj pri neki točki znotraj thread-a nadaljuje delo z drugim thread-om (ker itak čaka na opravljeno delo drugega thread-a)?

Gundolf ::

Ali obstaja v C-ju ukaz za procesor, naj pri neki točki znotraj thread-a nadaljuje delo z drugim thread-om (ker itak čaka na opravljeno delo drugega thread-a)?

To je uporaba condition variable. Narediš condition_vaf a; rečeš threadu 1 a.wait(); s čimer se le-ta ustavi (blokira) in čaka (čaka neaktivno - to pomeni da prepusti procesor drugim threadom). Medtem opraviš delo v threadu 2 in tam kličeš a.signal(); ki signalizira threadu 2, da lahko nadaljuje (ga odblokira). Ti le še najdi točno sintakso za condition var v winsih (tole moje je pseudo) pa boš imel zeljeno.

Torej imam TestWndProc proceduro, v kateri lovim določene message tega okna (WM_CREATE, WM_CLOSE, WM_COMMAND ...). Znotraj te procedure bi lahko jemal tudi message iz message queue, kamor bi jih dajal thread 1. Vsaj tako si predstavljam.

Jp, tu bi lovil tudi sporočila iz threada 1. Recimo da bi se imenovala WM_USER. Izmisliti si moraš le še neko uporabno strukturo za tvoja sporočila in pogledati, kako jih boš dejansko pošiljal iz threada 1. Morda se ti zna zakomplicirati s kazalci ;).

zlatko ::

To z 'conditional variable' je pa res dobra ideja. In ravno to potrebujem.

Je veliko govora na spletu o tem, vendar se mi zdi, da se vse to uporablja bolj v unix-u oz. linux-u. In pa tudi exampli so zelo raztreseni.

Zato bi te Gundolf prosil za kakšen primer iz windows-ov v C-ju oz. za kakšno spletno stran, kjer je bolj človeško opisanan uporaba struktur in kode na to temo.

Gundolf ::

No očitno windowsi to res drugače imenujejo in če se ne motim bi znalo biti tole
wait functions pravo. Še posebej funkcija WaitForSingleObject. Boš pa od tod tudi hitro našel vse kar hočeš vedeti in še malo več o drugih sinhronizacijskih tehnikah.

Aja šele zdajle sem opazil da želiš imeti stran, kjer je to človeško opisano, tako da ne vem če ti bo MSDN ravno najbolj ustrezal ;) Lahko pa sedaj pogooglaš WaitForSingleObject.

Vesoljc ::

lahko si pa tudi izbereš tudi kaj bolj konkretnega (prenosljivega). pthreads recimo, tudi boost ima par fajn stvari.
Abnormal behavior of abnormal brain makes me normal...

zlatko ::

Hvala vam za pomoč, sem si pomagal z Eventi ter z ukazoma SetEvent in WaitForSingleObject.

Čeprav zadeva deluje, z delom še nisem končal, ker v isti zanki čakam še na en event in sicer na odziv pri komunikaciji iz PIPE protokola s servisom. Tako da mi to nekaj nagaj ain ne gre skupaj.

Bom porihtal, hvala še enkrat.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Kaj je Hyper-threading

Oddelek: Strojna oprema
61372 (1080) PARTyZAN
»

Broadwell navsezadnje tudi za namizne računalnike

Oddelek: Novice / Procesorji
4514548 (12579) hojnikb
»

C/C++ Kako obvestim ostale threde, da je prispel nov podatek?

Oddelek: Programiranje
61398 (1262) ERGY
»

ali imam quad q9300?

Oddelek: Strojna oprema
121905 (1534) gendale
»

Odpiranje dat.exe v VB

Oddelek: Programiranje
122978 (2771) webblod

Več podobnih tem