Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Höjdpunkter
- Klassen DispatcherQueue i Windows App SDK hanterar en prioriterad kö där uppgifterna för en tråd körs på seriellt sätt.
- Det ger ett sätt för bakgrundstrådar att köra kod på en DispatcherQueue-tråd (till exempel UI-tråden där objekt med trådtillhörighet finns).
- Klassen integreras på ett exakt sätt med godtyckliga meddelandeloopar. Den stöder till exempel det gemensamma Win32-formspråket för kapslade meddelandeloopar.
- Klassen AppWindow integreras med DispatcherQueue – när en DispatcherQueue för en viss tråd stängs av förstörs AppWindow-instanserna automatiskt.
- Det ger ett sätt att registrera ett ombud som anropas när en tidsgräns upphör att gälla.
- Den innehåller händelser som meddelar komponenterna när en meddelandeloop avslutas och du kan också skjuta upp avstängningen tills det utestående arbetet har slutförts. Det säkerställer att komponenter som använder DispatcherQueue, men inte äger meddelandeloopen, kan rensa på tråden när loopen avslutas.
- DispatcherQueue är en tråd-singleton (det kan finnas högst en som körs på en viss tråd). Som standard har en tråd ingen DispatcherQueue.
- En trådägare kan skapa en DispatcherQueueController för att initiera DispatcherQueue för tråden. Vid den tidpunkten kan valfri kod komma åt trådens DispatcherQueue; men endast DispatcherQueueControllers ägare har åtkomst till metoden DispatcherQueueController.ShutdownQueue , som tömmer DispatcherQueue och genererar ShutdownStarting och ShutdownCompleted-händelser .
- En meddelandeslingas yttersta ägare måste skapa en DispatcherQueue-instans . Endast den kod som ansvarar för att köra en tråds yttersta meddelandeloop vet när sändningen är klar, vilket är rätt tid att stänga av DispatcherQueue. Det innebär att komponenter som förlitar sig på DispatcherQueue inte får skapa DispatcherQueue om de inte äger trådens meddelandeloop.
Nedgånget
När en tråd har avslutat händelseloopen måste den stänga av sin DispatcherQueue. Detta genererar händelserna ShutdownStarting och ShutdownCompleted och tömmer eventuella sista väntande objekt innan du inaktiverar ytterligare enqueuing.
- Om du vill stänga av en DispatcherQueue som körs på en dedikerad tråd med en DispatcherQueue-ägd meddelandeloop anropar du metoden DispatcherQueueController.ShutdownQueueAsync .
- För scenarier där appen äger en godtycklig meddelandeloop (till exempel XAML Islands) anropar du metoden Synchronous DispatcherQueueController.ShutdownQueue . Den metoden genererar avstängningshändelser och tömmer DispatcherQueue synkront på den anropande tråden.
När du anropar DispatcherQueueController.ShutdownQueueAsync eller DispatcherQueueController.ShutdownQueue är ordningen på händelser som genereras följande:
- ShutdownStarting. Avsedd att hanteras av appar.
- FrameworkShutdownStarting. Avsedd att hanteras av ramverk.
- FrameworkShutdownCompleted. Avsedd att hanteras av ramverk.
- ShutdownCompleted. Avsedd att hanteras av appar.
Händelserna är indelade i program-/ramverkskategorier så att ordnad avstängning kan uppnås. Det vill säga genom att uttryckligen höja programavstängningen före ramverksavstängningshändelser finns det ingen risk att en ramverkskomponent är i ett oanvändbart tillstånd när programmet avslutas.
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();
}
Yttersta och rekursiva meddelandeslingor
DispatcherQueue stöder anpassade meddelandeloopar. Men för enkla appar som inte behöver anpassning tillhandahåller vi en standardimplementering. Det tar bort en börda från utvecklare och hjälper till att säkerställa konsekvent korrekt beteende.
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();
}
Hantering av systemschemaläggare
Vissa Windows App SDK komponenter (till exempel MicaController) är beroende av systemkomponenter som i sin tur kräver ett system DispatcherQueue (Windows. System.DispatcherQueue) som körs på tråden.
I dessa fall anropar komponenten som har ett system DispatcherQueue-beroende metoden EnsureSystemDispatcherQueue , vilket frigör din app från att hantera ett system DispatcherQueue.
När den metoden anropas hanterar Windows App SDK DispatcherQueue automatiskt livslängden för systemets DispatcherQueue och stänger ned systemets DispatcherQueue tillsammans med Windows App SDK DispatcherQueue. Komponenter kan förlita sig på både Windows App SDK och system DispatcherQueue avstängningshändelser för att säkerställa att de gör rätt rensning efter att meddelandeloopen har avslutats.
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-integration
Klassen AppWindow har funktioner som integrerar den med DispatcherQueue, så att AppWindow-objekt automatiskt kan förstöras när metoden DispatcherQueueController.ShutdownQueueAsync eller DispatcherQueueController.ShutdownQueue anropas.
Det finns också en egenskap för AppWindow som gör det möjligt för anropande kod att hämta den DispatcherQueue som är associerad med AppWindow, vilket gör den konsekvent med andra objekt i namnrymderna Composition och Input.
AppWindow behöver din explicita opt-in för att vara medveten om DispatcherQueue.
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();
}
Windows developer