Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Destaques
- A classe DispatcherQueue na SDK de Aplicações Windows gere uma fila priorizada onde as tarefas de um thread são executadas de forma serial.
- Disponibiliza uma forma de as threads em segundo plano executarem código na thread de um DispatcherQueue (por exemplo, a thread da IU onde residem objetos com afinidade à thread).
- A classe integra-se precisamente com loops de mensagens arbitrários. Por exemplo, suporta a convenção comum do Win32 de ciclos de mensagens aninhados.
- A classe AppWindow integra-se com o DispatcherQueue — quando uma DispatcherQueue para um determinado thread está a ser encerrada, as instâncias do AppWindow são automaticamente destruídas.
- Fornece um meio de registar um delegado que é chamado quando um timeout expira.
- Fornece eventos que informam os componentes quando um ciclo de mensagens está a sair e, opcionalmente, adiam esse encerramento até que o trabalho pendente seja concluído. Isto garante que os componentes que usam a DispatcherQueue, mas não controlam o ciclo de mensagens, podem efetuar operações de limpeza no próprio thread quando o ciclo termina.
- O DispatcherQueue é um thread singleton (pode haver no máximo um deles a correr em qualquer thread). Por defeito, um thread não tem DispatcherQueue.
- O proprietário de um thread pode criar um DispatcherQueueController para inicializar o DispatcherQueue para o thread. Nesse momento, qualquer código pode aceder à DispatcherQueue do thread; mas apenas o proprietário do DispatcherQueueController tem acesso ao método DispatcherQueueController.ShutdownQueue , que drena a DispatcherQueue e gera os eventos ShutdownStarting e ShutdownCompletified .
- O proprietário do loop de mensagens mais externo deve criar uma instância DispatcherQueue . Só o código responsável por executar o ciclo de mensagens mais externo de um thread sabe quando o despacho está completo, que é o momento apropriado para desligar o DispatcherQueue. Isto significa que os componentes que dependem do DispatcherQueue não devem criar o DispatcherQueue a menos que possuam o ciclo de mensagens do thread.
Resumo
Depois de uma thread sair do respetivo ciclo de eventos, tem de encerrar a sua DispatcherQueue. Ao fazê-lo, desencadeia os eventos ShutdownStarting e ShutdownCompleted e processa todos os últimos itens pendentes colocados em fila antes de impedir que sejam colocados mais itens em fila.
- Para desligar um DispatcherQueue que está a correr num thread dedicado com um ciclo de mensagens pertencente ao DispatcherQueue, chame o método DispatcherQueueController.ShutdownQueueAsync .
- Para cenários em que a aplicação possui um ciclo de mensagens arbitrário (por exemplo, ilhas XAML), chame o método síncrono DispatcherQueueController.ShutdownQueue . Este método aciona eventos de encerramento e esvazia a DispatcherQueue de forma síncrona na thread de chamada.
Quando chama DispatcherQueueController.ShutdownQueueAsync ou DispatcherQueueController.ShutdownQueue, a ordem dos eventos apresentados é a seguinte:
- A iniciar o encerramento. Destina-se a ser processado por aplicações.
- O encerramento da framework está a iniciar. Destinado a ser tratado por estruturas.
- Desligamento do Framework Concluído. Destinado a ser tratado pelos frameworks.
- Encerramento concluído. Destinado a ser tratado por aplicações.
Os eventos são separados em categorias de aplicação/framework para que seja possível realizar um desligamento ordenado. Ou seja, ao assinalar explicitamente o encerramento da aplicação antes dos eventos de encerramento da estrutura, não há o perigo de um componente da estrutura ficar num estado inutilizável durante o encerramento da aplicação.
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();
}
Ciclos de mensagens mais externos e recursivos
O DispatcherQueue suporta ciclos de mensagens personalizados. No entanto, para aplicações simples que não precisam de personalização, fornecemos implementações padrão. Isso alivia um fardo aos programadores e ajuda a garantir um comportamento consistentemente correto.
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();
}
Gestão do despachante do sistema
Alguns componentes SDK de Aplicações Windows (por exemplo, MicaController) dependem de componentes do sistema que, por sua vez, requerem um sistema DispatcherQueue (Windows. System.DispatcherQueue) a correr na thread.
Nesses casos, o componente que tem uma dependência do sistema DispatcherQueue chama o método EnsureSystemDispatcherQueue, evitando que a sua aplicação tenha de gerir uma DispatcherQueue do sistema.
Com esse método chamado, o SDK de Aplicações Windows DispatcherQueue gere automaticamente a vida útil do sistema DispatcherQueue desligando automaticamente o sistema DispatcherQueue juntamente com o SDK de Aplicações Windows DispatcherQueue. Os componentes podem depender tanto dos eventos de encerramento do SDK de Aplicações Windows como dos eventos de encerramento da DispatcherQueue do sistema, para garantir que efetuam corretamente a limpeza depois de o ciclo de mensagens terminar.
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();
}
Integração com AppWindow
A classe AppWindow tem funcionalidades que a integram com a DispatcherQueue, de modo que os objetos AppWindow podem ser automaticamente destruídos quando o método DispatcherQueueController.ShutdownQueueAsync ou DispatcherQueueController.ShutdownQueue é chamado.
Existe também uma propriedade do AppWindow que permite aos chamadores recuperar o DispatcherQueue associado ao AppWindow; alinhando-o com outros objetos nos namespaces Composição e Entrada .
O AppWindow requer a sua aceitação explícita para reconhecer a 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