arckép

Neuwirth István

programtervező informatikus MSc – ELTE

Computational and Software Techniques MSc – Cranfield, UK

Elérhetőség
pitta2@gmail.com
+36 30 329 3039

Valid XHTML 1.0 Transitional

Valid CSS!

Aszinkron metódushívások

Mit tegyünk, ha bizonyos programrészeket párhuzamosan szeretnénk futtatni, de nem akarunk többszálú program megírásával vesződni? Mit tegyünk, hogy ha nem akarjuk, hogy egy hosszabb ideig tartó metódushívás blokkolja a programunkat? A fentiekre választ kaphattok az alábbiakban.

Normál esetben egy metódus meghívásakor az eredeti programrészlet futása megszakad, a metódus kódja lefut és visszatérünk a hívás helyére. Ameddig tehát tart a metódus kódjának futása, addig blokkolódik az eredeti és ez sokszor nem kívánatos. Legyen például egy alkalmazásunk, amely netről tölt le fájlokat és dolgozza fel őket. Egy ciklussal végigmegyünk az URL-ek gyűjteményén, kiépítjük a kapcsolatot, letöltjük a fájlt, majd feldolgozzuk egy megfelelő függvénnyel. A fenti megoldás hátránya, hogy a letöltés időtartama alatt nem tudunk foglalkozni a már letöltött tartalmakkal. Javíthatjuk a programot úgy, hogy a letöltést külön programszál végezze, így a feldolgozó függvény a letöltésekkel párhuzamosan dolgozhat. A többszálú programok fejlesztése meglehetősen körülményes, nehéz a hibákat felderíteni és kijavítani, és kiemelt figyelmet kell fordítanunk a szálak közötti szinkronizációra.

A fenti programot megírhatjuk explicit szálkezelés nélkül is: a .Net lehetőséget biztosít arra, hogy a megírt tagfüggvényeinket aszinkron módon is meghívhassuk, mégpedig delegate-ek, azaz metódusreferenciák segítségével. Metódusreferenciák formájában függvényeket paraméterek formájában is átadhatunk, majd ott meghívhatjuk őket (lásd C++ funktorok). Egy metódusreferencián keresztül egy neki megfelelő szignatúrájú függvényt tudunk visszahívni.

A példában egy string visszatérési értékkel és egy string paraméterrel rendelkező metódussal példányosítható a delegate. A háttérben a rendszer a deklaráció alapján egy megfelelő osztályt generál, amely segítségével a különböző típusú hívásokat végre tudjuk hajtani. Az Invoke(…) hatására normál módon hívhatunk, a kód a fő szálon fut le, a metódus szignatúrája megegyezik a metódusreferencia által várttal. Aszinkron módon a BeginInvoke/EndInvoke párossal hívhatunk, ekkor a példában a Download kódja egy külön szálon fut. A BeginInvoke már nem blokkol, illetve csak annyi ideig, amennyi a másik szál elindításához szükséges. Az aszinkron hívás eredményét lekérhetjük az EndInvoke segítségével, illetve feldolgozhatjuk egy másik függvénnyel.