Async sorosport
2020-11-19T11:47:58+01:00
2020-11-23T14:40:17+01:00
2022-07-20T12:46:52+02:00
  • Láttam már olyan helyet, ahol 10 évig rá se tojtak valamire, aztán hirtelen oda rángattak, hogy kerget-a-tatár stílusban gyorsan csináljam meg. "Mutass csak valami egyszerűt". Egy széket kerítettem oda, arra raktam egy helyileg valahonnét lejmolt számítógépet, abba lett bedugva a hálózati kábel, meg hosszabbítóval odavezetékezve a villany a számítógépnek. Még nem is álló kivitelezett ház volt, hanem a vízszintesen fekvő - régi rozzant vacak mechanikai stílus. Szóval megcsniáltam éppen csak bemutathatóra. Arra szántam, hogy majd újraépítem ugyan azt a funkciót mini pc-vel, normálisan felszerelem valahova, figyelek a kábelezésre, meg minden. De egyszer működött, megmutattam, soha többet a közelébe sem engedtek, hogy juj hímestojás Ipari munkaterületen egy rozzan széken távolról odahosszabbítozott árammal csücsült a bekábelezett gép, és az volt nekik a hímestojás. Az olyat a saját szemeddel kell látnod, hogy elhidd. Én fényképen látnám, azt mondanám fake, mert ekkora marhaságot meglát egy ellenőrzés, lekapcsoltatják az egész ipartelepet azonnal és nagyon megbüntetnek ott mindenkit. És még csak nem is magyar cég volt. Nevet nem írhatok, de egy tipikus üvegpalotás kérkedő fajta cégről van szó, amelyik kényes a tekintélyére. És közben meg olyat tesznek. Üdv Magyarországon.

    Szóval ne törd magad túl. Egyszer működik, hiába te csináltad, előfordulhat, többet téged se engednek a közelébe, hogy juj el fogod rontani Azóta már tudom, hogy a gyorsan-gyorsan-siessünk cégek mind olyanok.
    Mutasd a teljes hozzászólást!
  • Sziasztok!

    Végül is nem volt szükségem aszinkron megoldásra, mert egymást megváró kérdezz felelekek zajlanak, és megoldottam a különböző állapotokat a két received Event handlerben switch case-el.
    Mindenesetre köszönöm a sok hasznos hozzászólást, van még mit tanulnom bőven. A következő, hogy már bevezetés után megoldom aszinkron módon, ha már lesz időm játszani vele, és akkor mindenképp megosztom veletek, hátha majd láttok benne még hiányosságot.
    Köszi még egyszer!
    Mutasd a teljes hozzászólást!
  • Az ilyesmik jellemzően sima konzolos appok. Ha több idő van rá, lehet winforms try icon-ra le, ha még több idő van, akkor nt service, és még user login se kell a futásához. Ha kerget a tatár, a legegyszerűbbet szokás választani. Ha a számítógép dedikáltan csak arra kell, a fenét se zavar egy ott hagyott konzolos alkalmazás.

    Asp  Kell neki egy webkliens a soros port mellé. Mire akarjon webszervert?
    Mutasd a teljes hozzászólást!
  • Bevallom, nem olvastam végig az összes kommentet, de jó lenne tudni, hogy milyen alkalmazásról van szó - WinForms, WPF, ASP.NET Core, UWP, stb. Ettől függően választanék megoldást.

    ASP.NET Core esetén a WebHost/GenericHost-nak beépített támogatása van background task-ok futtatására az IHostedService interfészen keresztül. UWP esetén szintén van erre megoldás, az IBackgroundTask interfésszel.

    WPF és WinForms esetén viszont neked kell kézzel gondoskodni ennek a kialakításáról. Ebben az esetben Task.Run-nal elindítod a background task-ot, de nem await-eled. Viszont a programodnak biztosítania kell ennek a background task-nak egy CancellationToken-t, amivel jelezhet a programod a tasknak, hogy jó lenne gracefully leállni, ha a programot a user bezárja. Ebben az esetben a kivételkezelésre is nagyon oda kell figyelned. Mivel a Task nincs await-elve, így az egyetlen exception handler, ami el tudja kapni a kivételt, az a CLR lesz, ami pedig lelövi az alkalmazásodat. A background task magára van utalva, magának kell gondoskodnia a kivételkezelésről is.

    ASP.NET Core alkalmazás esetén SignalR-t használva real-time tudod küldeni az eseményeket a kliensnek egy Hub kialakításával. UWP, WPF és WinForms esetén pedig használhatod a hagyományos event-öket.

    Az implementáció lényege az, hogy a háttérfolyamat egy általad megadott időközönként pollozza a PLC-t, de csak akkor jelent, ha állapotváltozás lép fel.
    Mutasd a teljes hozzászólást!
  • A kislányhoz gratulálok. Vajon érteni fogsz annyira a felneveléséhez, hogy férjet is találj neki? Vagy téged fog az ujja köré csavarni és halálra szeretni?

    Oké, ha nyomás alatt kell alkotni, akkor általában nem erőltetünk szerkezeti kifinomultságot. Nincsenek adva a nyugodt munkavégzés feltételei, gyengébb lesz a minőség. Azért lesz úgy, mert a normálisabb minőség nem csak hozzáértésbe, de időbe is kerül, és ha az nincs, hát akkor nincs. Utólag ne engem szidj érte, hogy csak korlátos teljesítőképességű lesz az, ami elkészül. Kristálytiszta ugye?

    Szóval a szálakat elfelejted, és aszinkron jellegből is csak minimális lesz. Egy szálas szinkron módban működő program legtisztább szerkezete kb így néz ki:

    start:
    -alkalmazás initek
    -főciklus kilépésig
    end:

    Alkalmazás initekbe beleraksz soros porti előkészítést, webes kommunikátor adatait kitöltöd, előkészíted, amit lehet. Változókat mind kirakod public static-ba, egész programból közvetlenül  minden mindenhez hozzáférhessen. Modulok között adatokat a globális változókban adsz át. Azzal a szerkezettel lehet leggyorsabban ollózni és drótozni.

    A főciklusban elsőként a kilépési feltételt ellenőrzöd - ha van olyan, mint például lenyomtad az escape-et vagy akármi - és utána futtatod egyesével az alkalmazás modulokat, ha végére értél egyszer, continue, és futtatod végtelenségig, vagy amíg a kilépési feltételbe bele nem akadtál.

    A soros porti eszközből pld lentebb linkeltek egyet, én linkelek egy másikat, ami alfától omegáig kirészletez neked mindent:
    Serial Comms in C# for Beginners
    Az elején rá kell szánnod az időt, míg játszadozol vele, kivakarod a sallangot, ami neked nem kell, és csak a lényeges részek maradnak meg. Jellegében olyanra kell csiszolnod a darabot, hogy legyen egy init()-ed, ami után szinkronban ráhívhatsz read() vagy write() függvényekre időkorlátokkal. Write esetén azt nem adsz meg, és tart, ameddig tart. Read esetén ilyen 50 millisec elég lesz. A soros port egy olyan hardver, aminek van saját bufferje. Aztán oprendszer szintjén is van read cache. Elbír pár karakternyit anélkül, hogy neked rá kellene nézned. Nem kell folyton várni rá. Időnként ráhívsz, átveszed, ami már bufferben van, kiírod, amit ki akarsz írni, és hagyod a háttérben dolgozni az OS drivereit. A példában timerekkel csinálja meg, neked olyasmire nem lesz szükséged, főciklus lesz helyette, ami időnként szinkronban ráhív. Az időkorlát ahhoz kell, hogy ne várjon az idők végezetéig, amikor éppen nincs üzenet. A főciklus design olyan, hogy lehető legkisebb időszeletekbe szétszedni mindent, és max tized másodperc alatt lefusson, aztán pöröghessen újra meg újra. Ez a legegyszerűbb, ahogyan több külön feladatot összegyúrhatsz.

    A főciklusba a soros port mellé berakhatod a webes adat lekérőt (ha éppen van mit lekérdezni, szinkronban lekérdezed, ha nincs, visszatér a függvényed), pozíció ellenőrzést, meg amit akarsz.

    Hogy futószalagot, vagy mi a fenét vezérelsz vele, engem nagyon hidegen hagy

    Hálószobát meg ne felejtsd el rózsaszínűre festeni. Ha tudod, cseréltesd vastagabbra a fűrdőszobában a lefolyót. Ha nem, egy hátralévő életen át mérgelődhetsz majd rajta, hogy már megint melyikük hosszú hajától dugult el a lefolyó? Ha lány család lesztek, azt a problémát nem úszod meg
    Mutasd a teljes hozzászólást!
  • Először sima fájlművelettel logfájlból tudtam kiszedni az adatokat, de itt még a termék egy korábbi gyártási állapotban van, nekem meg teljesen a sor végén kellene ellenőriznem. Ha fájlból olvastan szépen működött a progi. fájl keletkezés -> adatlekérés > megjelenítés és logfileba írás. 
    aztán ez a félkész állapot el lett adva, hogy megoldás van egy régi problémára. Hozzáteszem vagy 10 éve megoldandó probléma, de mióta feljött, azóta két hét alatt meg kell oldani. Felterjesztették, és most a nagyok várják, hogy működjön a sor végén is. Nagyon nagy rajtam a nyomás, és már rég kész kellene, hogy legyen. Ja és nem utolsó sorban 4 napja megszületett a kislányom :)
    Van ott egy gép, aminek az egyik soros portjára a convejor, a másikra a szkenner csatlakozik. A szerverről az adatlekérés meg a többi nem probléma, az a része meg van.
    Tehát először arra várok, hogy megérkezzen a termék. szkennelek, majd arra várok, hogy megérkezzen a folyamatellenőrzés eredménye, majd arra várok, hogy a termék elhaladjon.
    Mutasd a teljes hozzászólást!
  • És persze immutable legyen az objektum, vagy más módon garantálja, hogy először ki van töltve az objektum, a store bufferekből lekerüljön legalább az L3 cache-be, mielőtt az objektum referenciája publikálásra kerül más szálak felé.
    Mutasd a teljes hozzászólást!
  • Hali!

    Próbáld meg felismerni, hogy mi a különbség a Tudástár (konkrét kérdések, megoldandó problémák színtere – ahol tévesen nyitottad ezt a témát) és a Társalgó (kötetlen beszélgetések, ötletelések, eszmecserék, viták, vélemény-, javaslat- és ajánlat-kérések helyszíne – ahol nyitnod kellett volna ezt a témát és ahova most áthelyeztem) között, és a jövőben új téma nyitásánál alkalmazd is ezt az ismeretet. Nem először szólok emiatt.

    Mutasd a teljes hozzászólást!
  • A konkrét szakmai részletek itt azért lényegtelenek, mert nem állás topicban vagyunk, hanem általános téma társalgójában. Elakadás van a "hogyan kell" kérdésénél. Aszinkron folyamatokról és szálakról írok alant egy kirészletezett szemléltetést, mivel is van az igazi probléma.

    Szóval van egy valós fizikai folyamat, ami gördülékenyen akar menni. Természetesen lehetne fejlett rendszert építeni, ami annak felismerésével kezdődne a számodra, hogy a dolgok nem egy pillanat alatt történnek meg. Egy folyamat elindulása az, ami egy pillanat alatt történik meg. Utána tart X ideig. Ha egy következő folyamatnak szüksége van az eredményére instant pillanatban, azt cache-elni szoktuk, amihez előre kell végrehajtani a folyamatot, és valahol helyben tárolni az eredményét, ami később már kivárási idő nélkül legyen elérhető. Írok egy példát. Be akarsz azonosítani egy terméket, ami megy a szalagon, hogy eldöntsd mi legyen vele. De akkor, amikor már ott van, neked kellene a döntés. A döntés nem lesz meg abban a pillanatban azért, mert a lekérdezési folyamat időt vesz igénybe, és esetleg maga a folyamat le is halhat, pld, mert túlterhelt az adat szerver. Szóval rossz esetben talán meg kell állítanod a szállítószalagot, vagy elfogadnod, hogy egy "talán problémás" termék tovább megy. Nyilván egyik sem a kedvenced. Amit például tehetsz, hogy egy előzetes pontban mintavételezed a szállítószalagon a tárgyak adatait, jó előre begyűjtöd a válaszokat a későbbi kérdésekre, és a szállítószalagon egy későbbi ponton hozol döntést arról, hogy kidobva legyen-e a tárgy. Minden ponton csak egy művelet (akár adatkérés elindítása, akár megérkezett végeredmény felhasználása), és minden ponton be kell kalkulálnod elégséges időt, hogy a háttér folyamat már le tudjon játszódni, mire fizikailag az a tárgy a szállítószalagon a vizsgálati pontból a döntéshozási pontba érkezett. Minden részfolyamatot listába veszel, és egyesével tervezed, hol indíthatod el az adat vizsgálatot, mennyi ideig tarthat az, hol lesz szükséged az eredményére.

    És még valami. "Gyorsítótárazni" az eredményt azt jelenti, hogy van egy dedikált számítógéped csak az adott feladatra ott a közvetlen közelben. Például azt írod, "soros porton", meg "weben". Na azokkal lenni tud pici probléma. Például ha a távolban lekapcsolják a webszervert, megállt az ipari termelés? Vagy 20 méter soros porti vezetékre valaki rácsukja az ajtót valahol, mikroszakadások éppen "szétkapcsolnak" a vezetékben, pont akkor nincs többet motor vezérlés a szállítószalagon, és menni fog időtlen időkig? Mert ha jól értettem, a plc a közvetlen vezérlést eldönti, de kell neki a felső szintű logika, mi alapján is valóítson meg vezérlést, és azt fizikailag egy távoli pontból adnád, amit kábeleznél - a kábelezéssel pedig tudnak éppen történni dolgok. Rövidebb legyen az a kábelezés, mint hogy bajos következményei lehessenek a hosszúságnak. Mert abban a kérdésben bizony a méret a lényeg. Nem ritkán pici elektronikákat használnak inkább, mint számítógépet egészben, mert a számítási kapacitás kevésbé fontos, mint a mechanikai környezet problémái. A szoftverek elektronikákon működnek, az elektronikák mechanikai realitásnak alárendeltek, azokról mind gondoskodnod kell ahhoz, hogy végül "te csak programozz". Ha nem figyeltél azzal eléggé, egy nevetséges gyakorlati tényező miatt fogja egy egyébként tökéletes program valahol a skálán a misztikus hibáktól a teljes működésképtelenségig terjedés jeleit mutatni sweep üzemben.

    Oké, ez így nem volt rövid, és nem azért írtam, hogy már megoldás legyen. Azért írtam, hogy szemléltessem a problémák részletességét, és az azokra odafigyeléssel járó lelki terhet, amiről el kell tudnod dönteni, bírni tudod-e, vagy a frászba kívánod? Amit én figyeltem meg pályafutásom során, többszörös kontextust érintő feladatokban nagyon számít, mennyi cérnája van valakinek. Sokszorta is az a fontosabb. A programozás maga sokkal könnyebb. A papírjaid pedig teljesen irrelevánsak egy gyakorlati probléma fényében. Te most nem állás felvételizel, te már ott vagy, és neked kell megcsinálnod. A számítógépek és elektronikák talán papírokat kérnek tőled? Vagy csak utasításokat várnak?

    Szóval csak a "hogyan kell" kérdésére visszatérve - mennyi cérnád van hozzá? Kevés - van valamennyi - oda neked az oroszlánt is?

    És még valami. Mennyire kerget éppen a tatár? Két hónapja már ég a ház, és a főnököd egy bdsm korbáccsal folyamatosan ver téged, míg el nem készül a megoldás, vagy ráér a kifinomult megoldás valamennyi ideig?
    Mutasd a teljes hozzászólást!
  • [[BBCODE_175040]]Először is az ismereteimről. alap szinten tanultam programozni, de azt inkább hagyjuk (középsuli). emelt szinten sose tanították. A munkahelyemen fut pár alkalmazás, amik úgy születtek, hogy mindig a problémához csiszoltam a tudásom. rengeteg olyan szerkezetet használok, amit tudom, hogy sokkal elegánsabban is meg lehet oldani, de a cél szentesíti az eszközt, és ha működik akkor... A sakkhoz hasonlítanám. Szeretek sakkozni, de nem tudok. konkrét nyitásokat, közép- és végjátékokat nem ismerek, csak játszok. viszont mindig tanulok újat. Szóval tanítsatok! A konkrét feladatom: adott egy konvejor, egy pannasonic plc-vel, Mewtocool protokol alapján megy a kommunikáció. ha érzékelem (timer kérdezgeti 500ms-ként a motor, a végállás szenzor, és a konvejor start mód állapotát: 011 ), hogy ott a termék, akkor egy QR kód olvasót triggerelek másik sorosporton, megkapom a sorozatszámát, majd ez alapján web service-en lekérem a folyamatát a terméknek. Ha rendben van, akkor a konvejornak küldök egy üzenetet, amit értelmez a plc program, és továbbengedi a terméket. de itt jön szóba a többszálúság, mert itt megint tudnom kell, hogy ott van e a termék, illetve azt is jó lenne tudni, hogy közben nem-e távolította el valaki, és nem került-e oda másik termék. ha nem jó a termék folyamata, akkor is üzenek a konvejornak, hogy sípoljon, és ne engedje tovább a terméket. Jelenleg úgy oldom meg, hogy a konveyor receive event handlerje vizsgálja hogy 011, ha igen triggereli scannert. scanner receive EH pedig intézi a folyamatellenőrzést, ill itt megállítom a conveyor timer-jét. ha jó a termék egy változót "pass" állapotra írok, és küldök a konvejornak egy mehet üzenetet, ami generál egy úja konvejor EH-t. itt a konvejor EH-ban switch-case-el vizsgálom a változót, hogy "pass", "timer", vagy "fail" állapotban van-e. ha a pass ág fut, és konvejor a mehet üzenetet nyugtázta, akkor változót visszaállítom "timer"-re és elindítom a konvejor timer-jét. taglalhatnám tovább de ebből már biztos érzed, a kuszaságot. inkább úgy lenne jó, ha scanner külön végezné a dolgát, egy változóban pedig ott lenne mindig a konvejor aktuális állapota, amihez főszálból akármikor hozzáférek, illetve visszafelé is kellene komunikálni, hogy tudja a konvejor szál, hogy most van ellenőrzés, és most kell figyelni, hogy eltávolítják-e a terméket, és ezt jelezni egy változóba. elég hosszúra sikerült, remélem érthető, ha nem kérdezz(etek)
    Mutasd a teljes hozzászólást!
  • Másodpercenként 2x akar állapotot olvasni, és ezt a beolvasott állapotot akarja elérhetővé tenni bármilyen egyéb szál(ak) számára. Ehhez a sok szál saját queue-val, az állapotgép, az eseményvezérelt programozás stb kicsit overkill. Ehhez bőven elég, ha a beolvasott állapottal létrehoz egy objektumot, amit egy egyszerű volatile írással publikál az olvasó szálak felé. Így az állapotváltozás atomikus lesz (ez felteszem lényeges), és még csak lockolással se kell foglalkozzon. 

    Amit viszont érdemes észben tartani, hogy arra semmi garancia, hogy 500ms-enként tényleg új állapot lesz publikálva. Az állapotot publikáló szál akkor fog futni, amikor az ütemező azt képes futtatni. Ha az olvasó szál is másodpercenként 2x olvas, akkor előállhat az a helyzet, hogy 1mp-ig nem lát új állapotot, mert pont úgy jön ki az időzítés. Ha elvárás a feladatban, hogy az olvasó ilyenkor mindig megvárja az író szálat, akkor ezt külön kezelni kell.
    Mutasd a teljes hozzászólást!
  • System.IO.SerialPort
    Itt a doksi és vannak valami példák is:
    SerialPort Class (System.IO.Ports)

    Az olvasóciklust tedd egy szálba és pakold egy stringbe vagy byte array-ba amit olvasott. Csak valami szinkronizáció is kell, pl nézd meg a lock nyelvi szerkezetet.
    Mutasd a teljes hozzászólást!
  • Amit leírtál, az 3 külön kérdés.

    Az egyik kérdés, hogy a soros portot hogyan tudod kezelni. Windows alatt file-t nyitsz meg, és alogikai file-ként írod / olvasod. File control-al tudsz módosítani paramétereket, mint pld 9600, 8, N, 1-et beállítani, és olyasmik. Ha ebben kell segítség, fókuszálj erre.

    A "hogyan kell megvalósítani.." alkalmazás szerkezettől is függ. Jó lenne tudni, milyen design-okban vagy otthon. A főciklus fogalmát ismered? Pollinggal készség szintjén tudsz fejleszteni? Az lenne a legyegyszerűbb. És belegyömöszölni mindent egyetlen főciklusba. Ha merészebb vagy, akkor kérdés, hogy az állapotgépekkel mennyire szívesen barátkozol? Problémásabbak, de lazább szerkezetet ad folyamatos fejlesztéshez. Ha csinálnád úgy, legyen az egy külön kérdés. Ha nem, maradj a főciklus alkalmazásánál.

    És a szálak. A szálakat közötti átadás tipikusan lock()-olt objektumba zárt változókon keresztül zajlik. Szálakat használni akkor merném javasolni, ha az aszinkron design már zéró kérdés lenne a számodra. Ha nem szoktál párhuzamos adat feldolgozáshoz, a szálak kb sírva fognak fakasztani. Mindig minden 10x bonyolultabb. Jó előre konténer osztályt gyártani, minden adat átadáshoz külön használatot tervezni. Feladat-relatív üzenet kezelő queue-kat építeni a saját kezelő függvényeikkel - azok kerülnek az alkalmazás singletonba, semmi más. Kell egyéni "postaládát" gyártani mindegyik feldolgozó szálnak. Aztán elindítani a szálakat, főciklust indítani mindegyik szálban. Üzenetekre szedni minden eseményt, feldolgozási folyamatot tervezni hozzá, és azon az alapon futtatni mindent. Ha nem feltétlen kell neked egész szervert egy adott feladatra dedikálni, akkora ágyúval lőni a verebet simán hü**eség

    Szívesen
    Mutasd a teljes hozzászólást!
  • Ugyan a .NET-es eszközökhöz nem értek, de ha nincs is direkt async soros port kezelési lehetőség, több szállal meg lehet oldani. Ahogy írtad, az egyik szál kezeli a portot, a másik a UI-t.

    Ha jól tudom két szál bool változókon keresztüli kommunikációja elég veszélyes mutatvány, de akkor hogyan érdemes?

    Ezt jól tudod, de épp ezért vannak olyan nyelvi eszközök, amivel ez biztonságossá tehető: lock, volatile és az Interlocked osztály amiket hirtelen kis guglizással találtam. (Inkább Javában vagyok otthon, a .NET-et csak nagy vonalakban ismerem.)
    Mutasd a teljes hozzászólást!
  • Szia!

    A kérdést mikor feltettem, kiválasztottam, hogy programozás - C#, illetve, ha megnyitom a kérdést a címkéje felett látszik, hogy C#.
    Mindenesetre köszi a válaszodat, de .Net környezetben fejlesztek.

    üdv,
    Keke
    Mutasd a teljes hozzászólást!
  • Hali!

    Egyszerűbb válaszolni, ha kiderül, hogy milyen programnyelven kell a megoldás...

    Pl. Delphi-ben TComPort komponens és TTimer használatával a timer eseménykezelőjébe teheted a comport írást, a TComPort.OnRxBuf vagy .OnRxChar eseménykezelőjébe a válasz feldolgozását.

    Ha nem akarsz a többszálúsággal foglalkozni, akkor TComPort.SynchMethod := smWindowSynch, így a fő szálban lesz végrehajtva a vételi eseménykezelő.

    Malom
    Mutasd a teljes hozzászólást!
  • Sziasztok!

    Azt szeretném valahogy megoldani, hogy a programom aszinkron módon tudjon kommunikálni a PLC-vel. 
    A feladat ezen része az lenne, hogy a plc-től mondjuk 500ms-ként kérdezgetem a szenzor és a motor álapotát, és a főszálban ezen állapotokhoz bármikor hozzá tudjak férni. 

    hogy kell megvalósítani, hogy ez a sorosport időzített lekérdezés aszinkron valósuljon meg, illetve min keresztül tudom elérni a főszálból az aktuális válaszokat a plc-től? Ha jól tudom két szál bool változókon keresztüli kommunikációja elég veszélyes mutatvány, de akkor hogyan érdemes?

    köszi a válaszokat előre is!
    Mutasd a teljes hozzászólást!
abcd