Compartir a través de


Contextos

En este documento se describe el rol de los contextos en el runtime de simultaneidad. Un subproceso que se adjunta a un programador se conoce como contexto de ejecución o simplemente contexto. La función Concurrency::wait y la clase Concurrency::Context le permiten controlar el comportamiento de los contextos. Use la función wait para suspender el contexto actual durante un periodo de tiempo especificado. Use la clase Context cuando necesite tener mayor control sobre cuándo los contextos se bloquean, desbloquean y ceden, o sobre cuándo desea suscribir en exceso el contexto actual.

SugerenciaSugerencia

El runtime de simultaneidad proporciona un programador predeterminado y, por tanto, no es necesario crear uno en la aplicación. Puesto que el programador de tareas ayuda a optimizar el rendimiento de las aplicaciones, se recomienda que comience con Parallel Patterns Library (PPL) o Biblioteca de agentes asincrónicos si no ha usado antes el runtime de simultaneidad.

La función de espera (wait)

La función Concurrency::wait cede de forma cooperativa la ejecución del contexto actual durante un número especificado de milisegundos. El runtime utiliza el tiempo cedido para realizar otras tareas. Una vez transcurrido el tiempo especificado, el runtime reprograma el contexto para la ejecución. Por consiguiente, la función wait podría suspender el contexto actual durante más tiempo que el valor proporcionado para el parámetro milliseconds.

Al pasar 0 (cero) para el parámetro milliseconds, se provoca que el runtime suspenda el contexto actual hasta que se proporcione a todos los demás contextos activos la oportunidad de realizar el trabajo. Esto le permite ceder una tarea a todas las demás tareas activas.

Ejemplo

Para obtener un ejemplo que usa la función wait para ceder el contexto actual y permitir que se ejecuten otros contextos, vea Cómo: Usar grupos de programación para influir en el orden de ejecución.

La clase Context

La clase Concurrency::Context 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 el contexto actual de forma cooperativa, y la capacidad de 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. Un contexto que se bloquea cede sus recursos de procesamiento para que el runtime pueda efectuar 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 runtime produce Concurrency::context_self_unblock si un contexto intenta desbloquearse.

Para bloquear y desbloquear de forma cooperativa un contexto, normalmente se llama a Concurrency::Context::CurrentContext para recuperar un puntero al objeto Context que está asociado al subproceso actual y guardar el resultado. Después puede llamar al método Context::Block para bloquear el contexto actual. Después, llame a Context::Unblock desde un contexto independiente para desbloquear el contexto bloqueado.

Debe emparejar cada par de llamadas a Context::Block y Context::Unblock. El runtime produce Concurrency::context_unblock_unbalanced cuando se llama al método Context::Block o Context::Unblock consecutivamente sin una llamada correspondiente 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, ese contexto permanece desbloqueado.

El método Concurrency::Context::Yield cede la ejecución para que el runtime pueda llevar a cabo otras tareas y, a continuación, reprogramar el contexto para la ejecución. Cuando se llama al método Context::Block, el runtime no reprograma el contexto.

Ejemplo

Para obtener un ejemplo en el que se usan los métodos Context::Block, Context::Unblock y Context::Yield para implementar una clase semáforo cooperativa, vea Cómo: Usar la clase Context para implementar un semáforo cooperativo.

Suscripción excesiva

El programador predeterminado crea el mismo número de subprocesos que los subprocesos de hardware disponibles. Puede utilizar la suscripción excesiva para crear subprocesos adicionales para un subproceso de hardware determinado.

Para operaciones intensivas, la suscripción excesiva normalmente no escala porque introduce sobrecarga adicional. Sin embargo, para las tareas que tienen una cantidad alta de latencia, por ejemplo, la lectura de datos desde el disco o desde una conexión de red, la suscripción excesiva puede mejorar la eficacia total de algunas aplicaciones.

Nota

Habilite la suscripción excesiva exclusivamente desde un subproceso que no sea UMS creado por el Runtime de simultaneidad. La suscripción excesiva no tiene ningún efecto cuando la llamada se produce desde un subproceso que no creó el runtime (aunque se trate del subproceso principal). Además, la suscripción excesiva no tiene ningún efecto cuando la llamada se realiza en un contexto en el que se usan subprocesos UMS para programar tareas, ya que los subprocesos UMS permiten al programador sacar el máximo partido de los recursos en presencia de operaciones de bloqueo.

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. Cuando se habilita la suscripción excesiva en un subproceso creado por el Runtime de simultaneidad, hace que el runtime cree un subproceso adicional. Después de que finalicen todas las tareas que requieren suscripción excesiva, llame a Context::Oversubscribe con el parámetro _BeginOversubscription establecido en false.

Puede habilitar varias veces la suscripción excesiva para el contexto actual, pero debe deshabilitarla el mismo número de veces que la habilita. La suscripción excesiva también puede estar anidada, es decir, una tarea creada por otra tarea que usa suscripción excesiva también puede suscribir en exceso su contexto. Sin embargo, si una tarea anidada y su elemento primario pertenecen al mismo contexto, solo la llamada más externa a Context::Oversubscribe causa la creación de un subproceso adicional.

Nota

El runtime produce Concurrency::invalid_oversubscribe_operation si la suscripción en exceso está deshabilitada antes de habilitarla.

Ejemplo

Para obtener un ejemplo que utiliza la suscripción en exceso para compensar la latencia que se produce leyendo los datos de una conexión de red, vea Cómo: Usar la suscripción excesiva para compensar la latencia.

Vea también

Tareas

Cómo: Usar la suscripción excesiva para compensar la latencia

Conceptos

Programador de tareas (Runtime de simultaneidad)

Otros recursos

Cómo: Usar grupos de programación para influir en el orden de ejecución

Cómo: Usar la clase Context para implementar un semáforo cooperativo

Historial de cambios

Fecha

Historial

Motivo

Julio de 2010

Contenido reorganizado.

Mejora de la información.