Contextos
En este documento se describe el rol de los contextos en el Runtime de simultaneidad. Un subproceso asociado a un programador se conoce como contexto de ejecución o, simplemente, contexto. La función concurrency::wait y la clase de contexto concurrency:: permiten controlar el comportamiento de los contextos. Use la función wait
para suspender el contexto actual durante un tiempo especificado. Use la clase Context
cuando necesite tener más control sobre cuándo los contextos bloquean, desbloquean y ceden, o cuando desee suscribir en exceso el contexto actual.
Sugerencia
Runtime de simultaneidad proporciona un programador predeterminado, por lo que no deberá crear uno en la aplicación. El Programador de tareas permite ajustar el rendimiento de las aplicaciones por lo que, si no está familiarizado con Runtime de simultaneidad, se recomienda comenzar con la biblioteca de modelos paralelos (PPL) o la biblioteca de agentes asincrónicos.
Función wait
La función concurrency::wait suspende de forma cooperativa la ejecución del contexto actual durante un número especificado de milisegundos. El tiempo de ejecución usa el tiempo de suspensión para realizar otras tareas. Una vez transcurrido el tiempo especificado, el tiempo de ejecución vuelve a programar el contexto para la ejecución. Por lo tanto, es posible que la función wait
suspenda el contexto actual durante más tiempo que el valor proporcionado para el parámetro milliseconds
.
Pasar 0 (cero) para el parámetro milliseconds
hace que el tiempo de ejecución suspenda el contexto actual hasta que los demás contextos activos tengan la oportunidad de realizar el trabajo. Esto le permite ceder una tarea para realizar las demás tareas activas.
Ejemplo
Para obtener un ejemplo que usa la función wait
para ceder el contexto actual y así permitir que se ejecuten otros contextos, consulte Cómo usar grupos de programación para influir en el orden de ejecución.
Clase de contexto
La clase de contexto concurrency:: proporciona una abstracción de programación para un contexto de ejecución y ofrece dos características importantes: la capacidad de bloquear, desbloquear y ceder de forma cooperativa el contexto actual y suscribir en exceso el contexto actual.
Bloqueo cooperativo
La clase Context
permite bloquear o ceder el contexto de ejecución actual. Bloquear o ceder es útil cuando el contexto actual no puede continuar porque un recurso no está disponible.
El método concurrency::Context::Block bloquea el contexto actual. Cuando se bloquea un contexto, este cede sus recursos de procesamiento para que el tiempo de ejecución pueda realizar otras tareas. El método concurrency::Context::Unblock desbloquea un contexto bloqueado. Se debe llamar al método Context::Unblock
desde un contexto diferente al que llamó a Context::Block
. El tiempo de ejecución produce concurrency::context_self_unblock si un contexto intenta desbloquearse.
Para bloquear y desbloquear un contexto de forma cooperativa, normalmente se llama a concurrency::Context::CurrentContext para recuperar un puntero al objeto Context
asociado al subproceso actual y guardar el resultado. A continuación, se llama al método Context::Block
para bloquear el contexto actual. Después, se llama a Context::Unblock
desde un contexto independiente para desbloquear el contexto bloqueado.
Debe hacer coincidir cada par de llamadas a Context::Block
y Context::Unblock
. El tiempo de ejecución produce concurrency::context_unblock_unbalanced cuando se llama al método Context::Block
o Context::Unblock
de forma consecutiva sin una llamada coincidente al otro método. Sin embargo, no es necesario llamar a Context::Block
antes de llamar a Context::Unblock
. Por ejemplo, si un contexto llama a Context::Unblock
antes de que otro contexto llame a Context::Block
para el mismo contexto, dicho contexto seguirá desbloqueado.
El método concurrency::Context::Yield suspende la ejecución para que el tiempo de ejecución pueda realizar otras tareas y, a continuación, vuelve a programar el contexto para su ejecución. Cuando se llama al método Context::Block
, el tiempo de ejecución no vuelve a programar el contexto.
Ejemplo
Para obtener un ejemplo que usa los métodos Context::Block
, Context::Unblock
y Context::Yield
para implementar una clase de semáforo cooperativo, consulte Cómo usar la clase de contexto para implementar un semáforo cooperativo.
Suscripción excesiva
El programador predeterminado crea tantos subprocesos como subprocesos de hardware disponibles haya. Puede usar la suscripción excesiva para crear subprocesos adicionales para un subproceso de hardware determinado.
En el caso de las operaciones que requieren gran cantidad de recursos de computación, la suscripción excesiva no se suele escalar porque supone una sobrecarga adicional. Sin embargo, por ejemplo, en el caso de las tareas que tienen una gran cantidad de latencia, la suscripción excesiva puede mejorar la eficacia general de algunas aplicaciones a la hora de leer datos del disco o de una conexión de red.
Nota:
Habilite la suscripción excesiva solo desde un subproceso creado por el Runtime de simultaneidad. La suscripción excesiva no tiene ningún efecto cuando se llama desde un subproceso que no creó el tiempo de ejecución (incluido el subproceso principal).
Para habilitar la suscripción excesiva en el contexto actual, llame al método concurrency::Context::Oversubscribe con el parámetro _BeginOversubscription
establecido en true
. Si habilita la suscripción excesiva en un subproceso creado por el Runtime de simultaneidad, el tiempo de ejecución creará un subproceso adicional. Una vez finalizadas todas las tareas que requieren una suscripción excesiva, llame a Context::Oversubscribe
con el parámetro _BeginOversubscription
establecido en false
.
Puede habilitar la suscripción excesiva varias veces desde el contexto actual, pero debe deshabilitarla el mismo número de veces que la habilite. También es posible anidar la suscripción excesiva; es decir, una tarea creada por otra tarea que usa la suscripción excesiva también puede suscribir su contexto en exceso. Sin embargo, si una tarea anidada y su elemento primario pertenecen al mismo contexto, solo la llamada más externa a Context::Oversubscribe
provocará la creación de un subproceso adicional.
Nota:
Si la suscripción excesiva está deshabilitada antes de habilitarse, el tiempo de ejecución produce concurrency::invalid_oversubscribe_operation.
Ejemplo
Para obtener un ejemplo en el que se usa la suscripción excesiva para compensar la latencia causada por la lectura de datos desde una conexión de red, consulte Cómo usar la suscripción excesiva para compensar la latencia.
Consulte también
Programador de tareas
Procedimiento para usar grupos de programación para influir en el orden de ejecución
Procedimiento para usar la clase Context para implementar un semáforo cooperativo
Procedimiento para usar la suscripción excesiva para compensar la latencia