Compartilhar via


Contextos

Este documento descreve a função de contextos no Runtime de Simultaneidade. Um thread anexado a um agendador é conhecido como um contexto de execução ou apenas contexto. A função concurrency::wait e a classe concurrency::Context permitem que você controle o comportamento dos contextos. Use a função wait para suspender o contexto atual por um tempo especificado. Use a classe Context quando precisar de mais controle sobre quando os contextos bloqueiam, desbloqueiam e suspendem ou quando desejar assinar o contexto atual.

Dica

O Runtime de Simultaneidade fornece um agendador padrão e, portanto, você não precisa criar um em seu aplicativo. Como o Agendador de Tarefas ajuda você a ajustar o desempenho de seus aplicativos, é recomendável que você comece com a PPL (Biblioteca de Padrões Paralelos) ou a Biblioteca de Agentes Assíncronos se você for novo no Runtime de Simultaneidade.

A Função wait

A função concurrency::wait produz cooperativamente a execução do contexto atual para um número especificado de milissegundos. O runtime usa o tempo de rendimento para executar outras tarefas. Depois que o tempo especificado tiver decorrido, o runtime reagenda o contexto para execução. Portanto, a função wait pode suspender o contexto atual por mais tempo do que o valor fornecido para o parâmetro milliseconds.

Passar 0 (zero) para o parâmetro milliseconds faz com que o runtime suspenda o contexto atual até que todos os outros contextos ativos recebam a oportunidade de executar o trabalho. Isso permite que você produza uma tarefa para todas as outras tarefas ativas.

Exemplo

Para obter um exemplo que usa a função wait para produzir o contexto atual e, portanto, permitir a execução de outros contextos, consulte Como usar grupos de agendamento para influenciar a ordem de execução.

A classe Context

A classe concurrency::Context fornece uma abstração de programação para um contexto de execução e oferece dois recursos importantes: a capacidade de bloquear, desbloquear e produzir cooperativamente o contexto atual e a capacidade de assinar o contexto atual.

Bloqueio cooperativo

A classe Context permite que você bloqueie ou produza o contexto de execução atual. O bloqueio ou o rendimento são úteis quando o contexto atual não puder continuar porque um recurso não está disponível.

O método concurrency::Context::Block bloqueia o contexto atual. Um contexto bloqueado gera seus recursos de processamento para que o runtime possa executar outras tarefas. O método concurrency::Context::Unblock desbloqueia um contexto bloqueado. O método Context::Unblock deve ser chamado de um contexto diferente daquele chamado Context::Block. O runtime gera concurrency::context_self_unblock se um contexto tentar desbloquear a si mesmo.

Para bloquear e desbloquear um contexto de forma cooperativa, normalmente você chama concurrency::Context::CurrentContext para recuperar um ponteiro para o objeto Context associado ao thread atual e salvar o resultado. Em seguida, você chama o método Context::Block para bloquear o contexto atual. Posteriormente, chame Context::Unblock de um contexto separado para desbloquear o contexto bloqueado.

Você deve corresponder a cada par de chamadas para Context::Block e Context::Unblock. O runtime gera concurrency::context_unblock_unbalanced quando o método Context::Block ou Context::Unblock é chamado consecutivamente sem uma chamada correspondente para o outro método. No entanto, você não precisa chamar Context::Block antes de chamar Context::Unblock. Por exemplo, se um contexto chamar Context::Unblock antes de outro contexto chamar Context::Block para o mesmo contexto, esse contexto permanecerá desbloqueado.

O método concurrency::Context::Yield gera execução para que o runtime possa executar outras tarefas e, em seguida, reagendar o contexto para execução. Quando você chama o método Context::Block, o runtime não reagenda o contexto.

Exemplo

Para obter um exemplo que usa os métodos Context::Block, Context::Unblock e Context::Yield para implementar uma classe de semáforo cooperativa, consulte Como usar a classe de contexto para implementar um semáforo cooperativo.

Excesso de assinatura

O agendador padrão cria o mesmo número de threads que o número de threads de hardware disponíveis. Você pode usar excesso de assinatura para criar threads adicionais para um determinado thread de hardware.

Para operações computacionalmente intensivas, o excesso de assinatura normalmente não é dimensionado porque introduz sobrecarga adicional. No entanto, para tarefas que têm uma alta quantidade de latência, por exemplo, ler dados de disco ou de uma conexão de rede, o excesso de assinatura pode melhorar a eficiência geral de alguns aplicativos.

Observação

Habilite o excesso de assinatura somente de um thread que tenha sido criado pelo Runtime de Simultaneidade. O excesso de assinatura não tem efeito quando é chamado de um thread que não tenha sido criado pelo runtime (incluindo o thread principal).

Para habilitar o excesso de assinatura no contexto atual, chame o método concurrency::Context::Oversubscribe com o _BeginOversubscription parâmetro definido como true. Quando você habilita o excesso de assinatura em um thread criado pelo Runtime de Simultaneidade, ele faz com que o runtime crie um thread adicional. Após todas as tarefas que exigem a conclusão do excesso de assinatura, chame Context::Oversubscribe com o parâmetro _BeginOversubscription definido como false.

Você pode habilitar o excesso de assinatura várias vezes no contexto atual, mas deve desabilitar o mesmo número de vezes que habilitá-lo. O excesso de assinatura também pode ser aninhado; ou seja, uma tarefa criada por outra tarefa que use excesso de assinatura também pode assinar em excesso seu contexto. No entanto, se uma tarefa aninhada e seu pai pertencerem ao mesmo contexto, apenas a chamada Context::Oversubscribe mais externa causará a criação de um thread adicional.

Observação

O runtime gera concurrency::invalid_oversubscribe_operation se o excesso de assinatura estiver desabilitado antes de ser habilitado.

Exemplo

Para obter um exemplo que usa o excesso de assinatura para compensar a latência causada pela leitura de dados de uma conexão de rede, consulte Como usar o excesso de assinatura para compensar a latência.

Confira também

Agendador de Tarefas
Como usar grupos agendados para influenciar a ordem de execução
Como usar a classe de contexto para implementar um semáforo cooperativo
Como usar excesso de assinatura para compensar a latência