Megosztás a következőn keresztül:


Várakozás az aszinkron válaszra

Az, hogy az ügyfél mire vár, hogy értesítést kapjon a kiszolgáló válaszáról, attól függ, hogy milyen értesítési mechanizmust választ.

Ha az ügyfél eseményt használ az értesítéshez, általában meghívja a WaitForSingleObject függvényt vagy a WaitForSingleObjectEx függvényt. Az ügyfél blokkolt állapotba kerül, amikor az egyik függvényt meghívja. Ez azért hatékony, mert az ügyfél nem használja fel a cpu-futtatási ciklusokat, amíg le van tiltva.

Amikor lekérdezéssel várja meg az eredményeket, az ügyfélprogram egy ciklust ad meg, amely ismételten meghívja a függvényt RpcAsyncGetCallStatus. Ez egy hatékony várakozási módszer, ha az ügyfélprogram más feldolgozást végez a lekérdezési ciklusban. Például előkészítheti az adatokat kis adattömbökben egy későbbi aszinkron távoli eljáráshíváshoz. Miután az egyes részek befejeződtek, az ügyfél lekérdezheti a folyamatban lévő aszinkron távoli eljáráshívást, hogy ellenőrizze, befejeződött-e.

Az ügyfélprogram képes aszinkron eljáráshívást (APC) biztosítani, ami egy például visszahívási függvény, amelyet az RPC futásidejű kódtár az aszinkron távoli eljáráshívás befejeződésekor meghív. Az ügyfélprogramnak riasztásos várakozási állapotban kell lennie. Ez általában azt jelenti, hogy az ügyfél meghív egy Windows API-függvényt, hogy blokkolt állapotba helyezze magát. További információ: Aszinkron eljáráshívások.

Jegyzet

Az aszinkron RPC-rutin nem küld értesítést a befejezésről, ha egy Aszinkron hívás során RPC-kivétel lép fel.

 

Ha az ügyfélprogram egy I/O befejezési portot használ a befejezési értesítés fogadásához, meg kell hívnia a GetQueuedCompletionStatus függvényt. Ha igen, határozatlan ideig várakozhat a válaszra, vagy folytathatja a további feldolgozást. Ha más feldolgozást végez, amíg a válaszra vár, le kell kérdeznie a befejezési portot a GetQueuedCompletionStatus függvénnyel. Ebben az esetben általában nullára kell állítania a dwMilliseconds. Emiatt GetQueuedCompletionStatus azonnal visszatér, még akkor is, ha az aszinkron hívás nem fejeződött be.

Az ügyfélprogramok az ablak üzenetsorain keresztül is kaphatnak befejezési értesítést. Ebben az esetben egyszerűen feldolgozzák a befejező üzenetet, ahogy bármilyen Windows-üzenetet.

Többszálú alkalmazásokban az aszinkron hívásokat az ügyfél csak azután mondhatja le, hogy a hívást kezdeményező szál sikeresen visszatért a hívásból. Ez biztosítja, hogy egy másik szál aszinkron módon ne mondja le a hívást, miután egy szinkron hívás meghiúsult. Szokásos eljárásként a szinkron módon meghiúsuló aszinkron hívásokat nem szabad aszinkron módon megszakítani. Az ügyfélalkalmazásnak megfigyelnie kell ezt a viselkedést, ha a hívásokat különböző szálakon lehet kibocsátani és megszakítani. A hívás megszakítása után az ügyfélkódnak meg kell várnia a befejezési értesítést, és végre kell hajtania a hívást. Az RpcAsyncCancelCall függvény egyszerűen sietteti a befejezési értesítést; nem helyettesíti a hívás befejezését.

Az alábbi kódrészlet bemutatja, hogyan használhat egy ügyfélprogram egy eseményt az aszinkron válaszra való várakozáshoz.

// This code fragment assumes that Async is a valid asynchronous
// RPC handle.
if (WaitForSingleObject(Async.u.hEvent, INFINITE) == WAIT_FAILED)
{
    RpcRaiseException(APP_ERROR);
}

Az APC-t használó ügyfélprogramok általában blokkolt állapotba helyezik magukat, ha aszinkron válaszról kapnak értesítést. Az alábbi kódrészlet ezt mutatja.

if (SleepEx(INFINITE, TRUE) != WAIT_IO_COMPLETION)
{
    RpcRaiseException(APP_ERROR);
}

Ebben az esetben az ügyfélprogram alvó állapotba kerül, és nem használ processzorciklusokat, amíg az RPC futásidejű kódtár nem hívja meg az APC-t (nem jelenik meg).

A következő példa egy olyan ügyfelet mutat be, amely egy I/O-befejezési portot használ az aszinkron válaszra való várakozáshoz.

// This code fragment assumes that Async is a valid asynchronous
// RPC handle.
if (!GetQueuedCompletionStatus(
         Async.u.IOC.hIOPort,
         &Async.u.IOC.dwNumberOfBytesTransferred,
         &Async.u.IOC.dwCompletionKey,
         &Async.u.IOC.lpOverlapped,
         INFINITE))
{
    RpcRaiseException(APP_ERROR);
}

Az előző példában a GetQueuedCompletionStatus hívása határozatlan ideig várakozik, amíg az aszinkron távoli eljáráshívás befejeződik.

Egy lehetséges buktató többszálú alkalmazások írásakor fordul elő. Ha egy szál távoli eljáráshívást hív meg, majd a küldés befejezéséről szóló értesítés fogadása előtt leáll, a távoli eljáráshívás sikertelen lehet, és az ügyfél csonkja bezárhatja a kapcsolatot a kiszolgálóval. Ezért a távoli eljárást hívó szálak nem fejezhetők be a hívás befejezése vagy megszakítása előtt, ha a viselkedés nem kívánatos.