Red de conocimiento informático - Problemas con los teléfonos móviles - Aplicación multiproceso VB.NET

Aplicación multiproceso VB.NET

Los desarrolladores han estado pidiendo a Microsoft que agregue más funciones multiproceso a VB, y lo mismo ocurre con VB. VB6 ya admite la creación de EXE, DLL y OCX multiproceso. Sin embargo, el uso de la palabra subprocesos múltiples puede no ser exacto. Por lo tanto, VB6 solo admite la ejecución de múltiples unidades de un solo subproceso. Una unidad es en realidad el espacio donde se ejecuta el código, y los límites de la unidad restringen el acceso del código a cualquier cosa fuera de la unidad.

Es diferente, admite la creación de aplicaciones con subprocesos libres. Esto significa que varios subprocesos pueden acceder al mismo conjunto de datos compartidos. Las siguientes secciones de este artículo analizarán algunos puntos básicos del subproceso múltiple.

Problema

Aunque VB6 admite múltiples unidades de un solo subproceso, no admite un modelo de subproceso libre, es decir, no permite que múltiples subprocesos utilicen el mismo conjunto de datos. . En muchos casos, es necesario crear un nuevo hilo para realizar el procesamiento en segundo plano, lo que puede mejorar la disponibilidad de la aplicación. De lo contrario, un proceso largo puede hacer que la respuesta del programa sea muy lenta, por ejemplo, si presiona el botón A cancelar. sin respuesta durante mucho tiempo.

Solución

Debido al uso de CLR (Common Language Runtime), tiene muchas características nuevas, una de las cuales es la capacidad de crear aplicaciones sin subprocesos.

Usar hilos

En Java, usar hilos es muy simple. Entraremos en detalles de esto más adelante, pero por ahora primero creemos un formulario simple que use un nuevo hilo para ejecutar un proceso en segundo plano. Lo primero que debe hacer es crear una tarea en segundo plano que se ejecute en un hilo nuevo. El siguiente código realiza una ejecución de procesamiento bastante larga: un bucle infinito:

Private Sub BackgroundProcess()

Dim i As Integer = 1

Do While True

ListBox1.Items.Add("Iteraciones: " i)

i = 1

Bucle

End Sub

Este código se repite infinitamente y agrega un elemento a un cuadro de lista en la tabla cada vez que se ejecuta. Si no estás familiarizado con él, encontrarás algunas diferencias entre este código y VB6:

Asigna un valor al declarar la variable Dim i As Integer = 1

. Operador i = 1 en lugar de i = i 1

Se utiliza la palabra clave No Call

Una vez que tenemos un controlador de trabajo, debemos asignar este código a un proceso de hilo e iniciar. él. Para ello utilizamos el objeto Thread, que forma parte del espacio de nombres System.Threading en las clases de arquitectura .NET. Al crear una instancia de una nueva clase de subproceso, le pasamos una referencia al bloque de código que se ejecutará en el constructor de la clase de subproceso. El siguiente código crea un nuevo objeto de hilo y le pasa una referencia a BackgroundProcess:

Dim t As Thread

t = New Thread(AddressOf Me.BackgroundProcess)

p >

t.Start()

El operador AddressOf crea un objeto delegado para el método BackgroundProcess. En , un delegado es un puntero de función orientado a objetos y con seguridad de tipos. Después de crear una instancia del subproceso, puede comenzar a ejecutar el código llamando al método Start() del subproceso.

Controlar el hilo

Una vez iniciado el hilo, puedes controlar su estado a través de un método del objeto del hilo.

Puede pausar la ejecución de un subproceso llamando al método Thread.Sleep. Este método puede recibir un valor entero para determinar el tiempo que tarda el subproceso en dormir. Tome el ejemplo anterior, si desea que los elementos de la lista aumenten más lentamente, puede realizar una llamada al método de suspensión:

Private Sub BackgroundProcess()

Dim i As Integer = 1

Hacer mientras sea verdadero

ListBox1.Items.Add("Iteraciones: " i)

i = 1

Thread.CurrentThread .Sleep(2000)

Loop

End Sub

CurrentThread es un valor de propiedad estática pública que le permite obtener una cotización del hilo en ejecución actual.

También puedes poner el hilo en estado de suspensión llamando a Thread.Sleep (System.Threading.Timeout.Infinite). Lo especial es que el tiempo de suspensión de esta llamada es incierto. Para interrumpir este sueño, puede llamar al método Thread.Interrupt.

Similar a la hibernación y las interrupciones son suspender y reanudar. Suspender le permite pausar un hilo hasta que otro hilo llame a Thread.Resume. La diferencia entre hibernación y suspensión es que esta última no pone inmediatamente el hilo en un estado de espera. El hilo no se bloqueará hasta que el tiempo de ejecución de .NET crea que es un lugar seguro para suspenderlo, mientras que la hibernación pondrá el hilo inmediatamente en un estado de espera. estado de espera.

Lo último que debemos introducir es Thread.Abort, que detiene la ejecución de un hilo. En nuestro ejemplo simple, si queremos agregar un botón para detener el procesamiento, es muy simple. Solo necesitamos llamar al método Thread.Abort, como se muestra a continuación:

Private Sub Button2_Click(ByVal sender As. System. Object, _

ByVal e As System.EventArgs) Maneja Button2.Click

t.Abort()

End Sub

Este Este es el poder de los subprocesos múltiples. La interfaz de usuario responde muy bien porque se ejecuta en un hilo separado y el procesamiento en segundo plano se ejecuta en otro hilo. Cuando el usuario presione el botón cancelar, se recibirá una respuesta inmediatamente y se detendrá el procesamiento.

El ejemplo anterior es sólo una aplicación bastante simple. Al programar, también es necesario utilizar muchas funciones complejas de subprocesos múltiples. Uno de los problemas es cómo pasar datos del programa dentro o fuera del constructor de la clase de subproceso. En otras palabras, para un proceso colocado en otro subproceso, no se le pueden pasar parámetros ni devolverle un valor. Esto se debe a que el proceso que pasa al constructor del subproceso no puede tener ningún parámetro ni valor de retorno. Para resolver este problema, puede encapsular su procedimiento en una clase para que los parámetros del método puedan usar los campos de la clase.

Aquí damos un ejemplo sencillo, si queremos calcular el cuadrado de un número, es decir:

Función Cuadrado(Valor ByVal As Doble) As Doble

Valor de retorno * Valor

Función final

Para usar este procedimiento en un hilo nuevo, lo encapsulamos en una clase:

Clase pública SquareClass

Valor público como doble

Cuadrado público como doble

Public Sub CalcSquare()

Cuadrado = Valor * Valor

End Sub

End Class

Utilice este código para iniciar el procedimiento CalcSquare en un nuevo hilo, de la siguiente manera:

Private Sub Button1_Click( ByVal remitente como sistema .Object, _

ByVal e As System.EventArgs) Maneja Button1.Click

Dim oSquare As New SquareClass()

t = New Thread(AddressOf oSquare .CalcSquare)

oSquare.Value = 30

t.Start()

End Sub

Cabe señalar que, después del Cuando se inició el hilo, no verificamos el valor cuadrado en la clase, porque incluso si llama al método de inicio del hilo, no puede garantizar que el método se ejecute inmediatamente. Hay varias formas de obtener un valor de otro hilo. El método utilizado aquí es el más simple, que consiste en activar un evento cuando se completa el hilo. Discutiremos otro método más adelante en la sincronización de subprocesos. El siguiente código agrega declaraciones de eventos a SquareClass.

Clase pública SquareClass

Valor público como doble

Cuadrado público como doble

Subproceso de evento público completo (por valor cuadrado como doble)

p>

Public Sub CalcSquare()

Cuadrado = Valor * Valor

RaiseEvent ThreadComplete(Cuadrado)

End Sub

Clase final

El método de capturar eventos en el código de llamada es similar a VB6. Aún debe declarar la variable WithEvents y manejar el evento en un proceso. La diferencia es que declara el proceso de manejo de eventos usando la palabra clave Handles en lugar del Object_Event que se usa generalmente en VB6.

Atenuar con eventos oSquare As SquareClass

Subbotón privado 1_Click(ByVal remitente como System.Object, _

ByVal e As System.EventArgs) Maneja el botón 1.Click

oSquare = New SquareClass()

t = Nuevo hilo(AddressOf oSquare.CalcSquare)

oSquare.Value = 30

t. Start()

End Sub

Sub SquareEventHandler(ByVal Square As Double) _

Maneja oSquare.ThreadComplete

MsgBox("El el cuadrado es "

Cuadrado)

End Sub

Para este método, debes prestar atención al proceso de manejo del evento. En este ejemplo, es SquareEventHandler. Se ejecutará en el hilo que generó el evento. No se ejecuta en el hilo de ejecución de la tabla.

Sincronización de subprocesos

En términos de sincronización de subprocesos, se proporcionan varios métodos. En el ejemplo del cuadrado anterior, desea sincronizar con el hilo que realiza el cálculo para esperar a que se complete y obtener el resultado. Otro ejemplo es si está ordenando una matriz en otro hilo, debe esperar a que se complete el procesamiento antes de usar la matriz. Para realizar estas sincronizaciones, se proporcionan la declaración SyncLock y el método Thread.Join.

SyncLock puede obtener un bloqueo único al que hace referencia un objeto, simplemente transfiera el objeto a SyncLock. Al obtener este bloqueo único, se asegura de que varios subprocesos no accedan a datos compartidos o al código que se ejecuta en varios subprocesos. Para obtener un bloqueo, puede utilizar un objeto más conveniente: el objeto System.Type asociado con cada clase. El objeto System.Type se puede obtener utilizando el método GetType:

Public Sub CalcSquare()

SyncLock GetType(SquareClass)

Cuadrado = Valor * Valor

End SyncLock

End Sub

El otro es el método Thread.Join, que le permite esperar un tiempo específico hasta que se complete un hilo. Thread.Join devolverá True si el hilo se completa antes del tiempo que especifique; de ​​lo contrario, devuelve False. En el ejemplo del cuadrado, si no desea utilizar el método para activar un evento, puede llamar al método Thread.Join para determinar si el cálculo está completo.

El código es el siguiente:

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click

Dim oSquare As New SquareClass()

t = Nuevo hilo(AddressOf oSquare.CalcSquare)

oSquare.Value = 30

t.Start()

Si t.Join(500) Entonces

MsgBox(oSquare.Square)

Fin si

Fin Sub

Para este método, es importante tener en cuenta que el proceso que maneja el evento, en este caso SquareEventHandler, se ejecutará en el hilo que generó el evento. No se ejecuta en el hilo de ejecución de la tabla.