Compartir a través de


Aplicaciones multiproceso (C# y Visual Basic)

Con Visual Basic y C#, se pueden crear aplicaciones que realicen varias tareas a la vez. Las tareas con la posibilidad de mantener otras tareas pueden ejecutarse en subprocesos separados, un proceso que se conoce como multithreading o subprocesamiento libre.

Las aplicaciones que utilizan multithreading son más receptivas a los datos proporcionados por el usuario porque la interfaz de usuario permanece activa cuando se ejecutan tareas con un consumo de procesador elevado en subprocesos independientes. El multithreading también es útil cuando se crean aplicaciones escalables, porque se pueden agregar subprocesos a medida que aumenta la carga de trabajo.

Nota

Visual Studio 2010 y .NET Framework 4 mejoran la compatibilidad de la programación paralela proporcionando un nuevo runtime, nuevos tipos de biblioteca de clases y nuevas herramientas de diagnóstico.Para obtener más información, vea Programación paralela en .NET Framework.

Utilizar el componente BackgroundWorker

La manera más confiable de crear una aplicación multiproceso consiste en utilizar el componente BackgroundWorker. Esta clase administra un subproceso independiente dedicado a procesar el método que se especifique. Para obtener un ejemplo, vea Tutorial: Multithreading con el componente BackgroundWorker (C# y Visual Basic).

Para iniciar una operación en segundo plano, cree un componente BackgroundWorker que escuche los eventos que indican el progreso de la operación y señale la finalización de la operación. Puede crear el objeto BackgroundWorker mediante programación o puede arrastrarlo al formulario desde la ficha Componentes del Cuadro de herramientas. Si crea BackgroundWorker en el Diseñador de formularios, aparece en la Bandeja de componentes y sus propiedades se muestran en la ventana Propiedades.

Configuración para una operación en segundo plano

Para preparar una operación en segundo plano, agregue un controlador de eventos al evento DoWork. Llame a la operación que consume tiempo en este controlador de eventos.

Para iniciar la operación, llame a RunWorkerAsync. Para recibir notificaciones de actualizaciones del progreso, controle el evento ProgressChanged. Para recibir una notificación cuando finalice la operación, controle el evento RunWorkerCompleted.

Los métodos que controlan los eventos ProgressChanged y RunWorkerCompleted pueden tener acceso a la interfaz de usuario de la aplicación, ya que se inician en el subproceso que ha llamado el método RunWorkerAsync. Sin embargo, el controlador de eventos DoWork no puede trabajar con ningún objeto de la interfaz de usuario porque se ejecuta en el subproceso en segundo plano.

Crear y usar subprocesos

Si necesita más control sobre el comportamiento de los subprocesos de la aplicación, puede administrar los subprocesos personalmente. Sin embargo, debe ser consciente de que escribir aplicaciones multiproceso correctas puede ser difícil: la aplicación puede dejar de responder o experimentar errores transitorios debido a las condiciones de carrera. Para obtener más información, vea Componentes seguros para subprocesos.

Se crea un subproceso mediante la declaración de una variable de tipo Thread y una llamada al constructor al que se proporciona el nombre del procedimiento o método que se desea ejecutar en el nuevo subproceso. El código siguiente proporciona un ejemplo.

Dim newThread As New System.Threading.Thread(AddressOf AMethod)
System.Threading.Thread newThread =
    new System.Threading.Thread(AMethod);

Iniciar y detener subprocesos

Para iniciar la ejecución de un nuevo subproceso, utilice el método Start, tal y como se muestra en el código siguiente.

newThread.Start()
newThread.Start();

Para detener la ejecución de un subproceso, utilice el método Abort, tal y como se muestra en el código siguiente.

newThread.Abort()
newThread.Abort();

Además de iniciar y detener subprocesos, también se pueden pausar los subprocesos llamando al método Sleep o Suspend, reanudar un subproceso suspendido mediante el método Resume y anular un subproceso mediante el método Abort.

Métodos de subproceso

En la tabla siguiente se muestran algunos de los métodos que se pueden usar para controlar subprocesos individuales.

Método

Acción

Start

Inicia la ejecución de un subproceso.

Sleep

Hace una pausa en la ejecución de un subproceso durante un período de tiempo determinado.

Suspend

Hace una pausa en la ejecución de un subproceso cuando alcanza un punto seguro.

Abort

Detiene un subproceso cuando alcanza un punto seguro.

Resume

Reinicia un subproceso suspendido

Join

Hace que el subproceso actual espere a que termine otro subproceso. Si se utiliza con un valor de tiempo de espera, este método devuelve True cuando el subproceso termina en el tiempo asignado.

Puntos seguros

La mayoría de estos métodos son autoexplicativos, pero es posible que el concepto de puntos seguros resulte nuevo. Los puntos seguros son ubicaciones del código donde Common Language Runtime puede realizar, de forma automática y segura, la recolección de elementos no utilizados (el proceso de liberar variables no utilizadas y reclamar memoria). Cuando se llama a los métodos Abort o Suspend de un subproceso, Common Language Runtime analiza el código y determina la ubicación de un lugar adecuado para que el subproceso detenga su ejecución.

Propiedades de subprocesos

Los subprocesos contienen también varias propiedades útiles, como se muestra en la tabla siguiente:

Propiedad

Valor

IsAlive

Contiene el valor True si un subproceso está activo.

IsBackground

Obtiene o establece un valor de tipo Boolean que indica si un subproceso está o debe estar en segundo plano. Los subprocesos en segundo plano son como los de primer plano, pero los de segundo plano no impiden que se termine un proceso. Una vez terminados todos los subprocesos en primer plano pertenecientes a un proceso, Common Language Runtime termina el proceso mediante una llamada al método Abort en los subprocesos en segundo plano que continúan activos.

Name

Obtiene o establece el nombre de un subproceso. Suelen utilizarse para detectar subprocesos individuales durante la depuración.

Priority

Obtiene o establece un valor que el sistema operativo utiliza para asignar prioridades en la programación de subprocesos.

ApartmentState

Obtiene o establece el modelo de subprocesos utilizado para un subproceso en particular. Los modelos de subprocesos son importantes cuando un subproceso llama a código no administrado.

ThreadState

Contiene un valor que describe el estado o estados de un subproceso.

Prioridades de los subprocesos

Cada subproceso tiene una propiedad de prioridad, que determina qué porción de tiempo del procesador tarda en ejecutarse. El sistema operativo asigna mayores porciones de tiempo a los subprocesos de alta prioridad y menores a los subprocesos de baja prioridad. Los nuevos subprocesos se crean con el valor de Normal, pero puede cambiar la propiedad Priority a cualquier valor de la enumeración ThreadPriority.

Vea ThreadPriority para obtener una descripción detallada de las diversas prioridades de los subprocesos.

Subprocesos de primer y segundo plano

Un subproceso en primer plano se ejecuta de forma indefinida, mientras que un subproceso en segundo plano finaliza en cuanto el último subproceso en primer plano se detiene. Puede utilizar la propiedad IsBackground para determinar o cambiar el estado de segundo plano de un subproceso.

Multithreading con formularios y controles

Aunque el multithreading se adapta mejor a los métodos de clase y procedimientos en ejecución, también puede utilizarlo con formularios y controles. Si lo hace, tenga en cuenta los puntos siguientes:

  • Siempre que sea posible, ejecute los métodos de un control únicamente en el subproceso con el cual haya sido creado. Si hay que llamar a un método de un control desde otro subproceso, utilice Invoke para invocar el método.

  • No utilice la instrucción SyncLock (Visual Basic) ni lock (C#) para bloquear subprocesos que manipulen controles o formularios. Puesto que los métodos de los controles y los formularios algunas veces devuelven la llamada a un procedimiento que realizó la llamada, puede que sin darse cuenta acabe creando un interbloqueo: una situación en la cual dos subprocesos esperan cada uno a que el otro libere el bloqueo, provocando que se detenga la aplicación.

Vea también

Referencia

Sincronización de subprocesos (C# y Visual Basic)

Invoke

InvokeRequired

Thread

Conceptos

Parámetros y valores devueltos para procedimientos multiproceso (C# y Visual Basic)

Otros recursos

Subprocesamiento múltiple en componentes

Cómo crear un subproceso mediante C#