DispatcherQueue

Legfontosabb tudnivalók

  • A Windows App SDK DispatcherQueue osztálya egy prioritás szerinti üzenetsort kezel, amelyben a szál feladatai egymás után hajtódnak végre.
  • Lehetőséget biztosít arra, hogy a háttérszálak kódot futtassanak a DispatcherQueue szálán (például a felhasználói felület azon szálán, amelyhez szálhoz kötött objektumok tartoznak).
  • Az osztály pontosan integrálható tetszőleges üzenethurokkal. Támogatja például a beágyazott üzenethurkok gyakori Win32-kifejezését.
  • Az AppWindow osztály integrálva van a DispatcherQueue-vel – amikor egy adott szálhoz tartozó DispatcherQueue le van állítva, az AppWindow-példányok automatikusan megsemmisülnek.
  • Lehetővé teszi egy olyan delegált regisztrálását, amely meghívásra kerül, amikor az időkorlát lejár.
  • Olyan eseményeket biztosít, amelyek jelzik az összetevőknek, amikor egy üzenethurok leáll, és igény szerint elhalasztható a leállítás a függőben lévő feladatok befejezéséig. Ez biztosítja, hogy azok az összetevők, amelyek a DispatcherQueue-t használják, de nem ők kezelik az üzenetciklust, a ciklus leállásakor a szálon végezhessék el a tisztítási műveleteket.
  • A DispatcherQueue egy önálló szál (legfeljebb az egyik futtatható egy adott szálon). Alapértelmezés szerint egy szálnak nincs DispatcherQueue értéke.
  • A szál tulajdonosa létrehozhat egy DispatcherQueueControllert a szál DispatcherQueue elemének inicializálásához. Ezen a ponton bármely kód hozzáférhet a szál DispatcherQueue-éhez; de csak a DispatcherQueueController tulajdonosának van hozzáférése a DispatcherQueueController.ShutdownQueue metódushoz, amely kiüríti a DispatcherQueue-t, és a ShutdownStarting és a ShutdownCompleted eseményeket indít el.
  • A legkülső üzenethurok tulajdonosának létre kell hoznia egy DispatcherQueue-példányt . Csak a szál legkülső üzenethurok futtatásáért felelős kód tudja, hogy mikor fejeződik be a küldés, és ez a megfelelő időpont a DispatcherQueue leállításához. Ez azt jelenti, hogy a DispatcherQueue-ra támaszkodó összetevőknek csak akkor szabad létrehozniuk a DispatcherQueue-t , ha azok a szál üzenethurkával rendelkeznek.

Összefoglaló

Miután egy szál kilép az eseményhurkból, le kell állítania a DispatcherQueue-t. Ennek során a ShutdownStarting és a ShutdownCompleted eseményeket aktiválja, és a végleges függőben lévő, lekérdezett elemeket kiüríti, mielőtt letiltja a további lekérést.

  • Ha egy dedikált szálon futó DispatcherQueue-t szeretne leállítani egy DispatcherQueue-tulajdonú üzenethurokkal, hívja meg a DispatcherQueueController.ShutdownQueueAsync metódust.
  • Olyan esetekben, amikor az alkalmazás egy tetszőleges üzenethurkot kezel (például XAML Islands esetén), hívja meg a szinkron DispatcherQueueController.ShutdownQueue metódust. Ez a módszer leállítási eseményeket indít el, és szinkron módon üríti a DispatcherQueue-t a hívó szálon.

A DispatcherQueueController.ShutdownQueueAsync vagy a DispatcherQueueController.ShutdownQueue hívása esetén a létrehozott események sorrendje a következő:

  • A leállítás elindul. Alkalmazások általi kezelésre szolgál.
  • FrameworkShutdownStarting. A keretrendszerek általi kezelésre szolgál.
  • FrameworkShutdownCompleted. A keretrendszerek kezelésére szolgál.
  • ShutdownCompleted. Alkalmazások általi kezelésre szolgál.

Az események alkalmazás-/keretrendszerkategóriákra vannak osztva, hogy rendezett leállítást lehessen elérni. Ez azt jelenti, hogy az alkalmazás leállításának kifejezetten a keretrendszerleállítási események előtt történő növelésével nincs veszély arra nézve, hogy egy keretrendszer-összetevő használhatatlan állapotban lesz az alkalmazás leállása során.

namespace winrt 
{
    using namespace Microsoft::UI::Dispatching;
}

// App runs its own custom message loop.
void RunCustomMessageLoop()
{
    // Create a DispatcherQueue.
    auto dispatcherQueueController{winrt::DispatcherQueueController::CreateOnCurrentThread()};

    // Run a custom message loop. Runs until the message loop owner decides to stop.
    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!ContentPreTranslateMessage(&msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    // Run down the DispatcherQueue. This single call also runs down the system DispatcherQueue
    // if one was created via EnsureSystemDispatcherQueue:
    // 1. Raises DispatcherQueue.ShutdownStarting event.
    // 2. Drains remaining items in the DispatcherQueue, waits for deferrals.
    // 3. Raises DispatcherQueue.FrameworkShutdownStarting event.
    // 4. Drains remaining items in the DispatcherQueue, waits for deferrals.
    // 5. Disables further enqueuing.
    // 6. Raises the DispatcherQueue.FrameworkShutdownCompleted event.
    // 7. Raises the DispatcherQueue.ShutdownCompleted event.    

    dispatcherQueueController.ShutdownQueue();
}

Legkülső és rekurzív üzenetciklusok

A DispatcherQueue támogatja az egyéni üzenethurkokat. A testreszabást nem igénylő egyszerű alkalmazások esetében azonban alapértelmezett implementációkat biztosítunk. Ez eltávolítja a terhet a fejlesztőktől, és segít a következetesen helyes viselkedés biztosításában.

namespace winrt 
{
    using namespace Microsoft::UI::Dispatching;
}

// Simple app; doesn't need a custom message loop.
void RunMessageLoop()
{
    // Create a DispatcherQueue.
    auto dispatcherQueueController{winrt::DispatcherQueueController::CreateOnCurrentThread()};

    // Runs a message loop until a call to DispatcherQueue.EnqueueEventLoopExit or PostQuitMessage.
    dispatcherQueueController.DispatcherQueue().RunEventLoop();

    // Run down the DispatcherQueue. 
    dispatcherQueueController.ShutdownQueue();
}

// May be called while receiving a message.
void RunNestedLoop(winrt::DispatcherQueue dispatcherQueue)
{
    // Runs a message loop until a call to DispatcherQueue.EnqueueEventLoopExit or PostQuitMessage.
    dispatcherQueue.RunEventLoop();
}

// Called to break out of the message loop, returning from the RunEventLoop call lower down the
// stack.
void EndMessageLoop(winrt::DispatcherQueue dispatcherQueue)
{
    // Alternatively, calling Win32's PostQuitMessage has the same effect.
    dispatcherQueue.EnqueueEventLoopExit();
}

Rendszerdiszpécser-kezelés

Egyes Windows App SDK-összetevők (például MicaController) olyan rendszerösszetevőktől függenek, amelyek viszont a szálon futó rendszerbeli DispatcherQueue-t (Windows.System.DispatcherQueue) igényelnek.

Ezekben az esetekben a System DispatcherQueue függőséget tartalmazó összetevő az EnsureSystemDispatcherQueue metódust hívja meg, így az alkalmazás nem kezelheti a System DispatcherQueue rendszert.

A metódus meghívásakor a Windows App SDK DispatcherQueue automatikusan kezeli a rendszer DispatcherQueue életciklusát, és a rendszer DispatcherQueue-ját a Windows App SDK DispatcherQueue-val együtt állítja le. Az összetevők a Windows App SDK és a rendszer DispatcherQueue leállítási eseményekre is támaszkodhatnak annak érdekében, hogy az üzenethurok kilépése után a megfelelő törlést elvégezhessék.

namespace winrt 
{
    using namespace Microsoft::UI::Composition::SystemBackdrops;
    using namespace Microsoft::UI::Dispatching;
}

// The Windows App SDK component calls this during its startup.
void MicaControllerInitialize(winrt::DispatcherQueue dispatcherQueue)
{
    dispatcherQueue.EnsureSystemDispatcherQueue();

    // If the component needs the system DispatcherQueue explicitly, it can now grab it off the thread.
    winrt::Windows::System::DispatcherQueue systemDispatcherQueue =
        winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
}

void AppInitialize()
{
    // App doesn't need to concern itself with the system DispatcherQueue dependency.
    auto micaController = winrt::MicaController();
}

AppWindow-integráció

Az AppWindow osztály olyan funkciókkal rendelkezik, amelyek integrálják a DispatcherQueue-vel, így az AppWindow-objektumok automatikusan megsemmisíthetők a DispatcherQueueController.ShutdownQueueAsync vagy a DispatcherQueueController.ShutdownQueue metódus meghívásakor.

Az AppWindow rendelkezik egy tulajdonsággal is, amely lehetővé teszi a hívók számára az AppWindowhoz társított DispatcherQueue lekérését; a Kompozíció és a Bemeneti névterek más objektumaival való igazítása.

Az AppWindow-nak explicit bejelentkezésre van szüksége ahhoz, hogy tisztában legyen a DispatcherQueue-ről.

namespace winrt 
{
    using namespace Microsoft::UI::Dispatching;
    using namespace Microsoft::UI::Windowing;
}

void Main()
{
    // Create a Windows App SDK DispatcherQueue.
    auto dispatcherQueueController{winrt::DispatcherQueueController::CreateOnCurrentThread()};

    auto appWindow = AppWindow::Create(nullptr, 0, dispatcherQueueController.DispatcherQueue());

    // Since we associated the DispatcherQueue above with the AppWindow, we're able to retrieve it 
    // as a property. If we were to not associate a dispatcher, this property would be null.
    ASSERT(appWindow.DispatcherQueue() == dispatcherQueueController.DispatcherQueue());

    // Runs a message loop until a call to DispatcherQueue.EnqueueEventLoopExit or PostQuitMessage.
    dispatcherQueueController.DispatcherQueue().RunEventLoop();

    // Rundown the Windows App SDK DispatcherQueue. While this call is in progress, the AppWindow.Destoyed
    // event will be raised since the AppWindow instance is associated with the DispatcherQueue.
    dispatcherQueueController.ShutdownQueue();
}