Cómo sincronizar el acceso a un recurso compartido en un entorno de subprocesamiento múltiple con Visual Basic .NET o Visual Basic 2005

Seleccione idioma Seleccione idioma
Id. de artículo: 316136 - Ver los productos a los que se aplica este artículo
Este artículo se ha archivado. Se ofrece "tal cual" y no se volverá a actualizar.
Expandir todo | Contraer todo

En esta página

Resumen

Las aplicaciones de Visual Basic .NET o Visual Basic 2005 pueden realizar varias tareas simultáneamente mediante subprocesamiento múltiple. Subprocesamiento múltiple puede iniciar diferentes subprocesos para realizar tareas diferentes simultáneamente y el subprocesamiento múltiple mejora el rendimiento y capacidad de respuesta de las aplicaciones.

Puesto que varios subprocesos pueden tener acceso a un recurso al mismo tiempo, puede que desee sincronizar subprocesos individuales con otras partes del programa. Este artículo describe algunos escenarios comunes con programación de subprocesamiento múltiple y explica cómo sincronizar el acceso a un recurso compartido entre varios subprocesos.

Cómo proteger los datos globales en los módulos en un entorno multiproceso

Los campos públicos en los módulos son accesibles para todos los subprocesos en la aplicación. Para sincronizar el acceso a los campos públicos, puede utilizar la propiedad en lugar del campo y utilizar un objeto ReaderWriterLock para controlar el acceso. Para ello, siga estos pasos:
  1. Abra Visual Studio .NET o Visual Studio 2005.
  2. En el menú archivo , haga clic en Nuevo proyecto .
  3. En la vista de árbol de la izquierda, seleccione Visual Basic y a continuación, seleccione Aplicación de consola en la vista lista de la derecha. Presione ENTRAR.
  4. Module1 se genera automáticamente. Elimine todo el código de Module1 y, a continuación, pegue el código siguiente en Module1:
    Option Explicit On 
    Option Strict On
    
    Imports System
    Imports System.Threading
    
    Module Module1
    
        Sub Main()
            Dim threadArray(20) As Thread
            Dim threadNum As Integer
    
            'Create 20 threads.
            For threadNum = 0 To 19
                threadArray(threadNum) = New Thread(AddressOf AccessGlobalResource)
            Next threadNum
    
            'Start the threads.
            For threadNum = 0 To 19
                threadArray(threadNum).Start()
            Next
    
            'Wait until all of the thread spawn out finish.
            For threadNum = 0 To 19
                threadArray(threadNum).Join()
            Next
    
            Console.WriteLine("All operations have completed. Press enter to exit")
            Console.ReadLine()
        End Sub
    
        Sub AccessGlobalResource()
            Dim rnd As New Random()
            Dim theNumber As Long
    
            If rnd.Next Mod 2 <> 0 Then
                theNumber = Number
            Else
                theNumber = rnd.Next
                Number = theNumber
            End If
        End Sub 'AccessGlobalResource
    End Module
    
    					
  5. Haga clic con el botón secundario en el proyecto en Explorador de soluciones y, a continuación, haga clic en Agregar o agregar módulo . Agregar Module2.vb al proyecto.

    Nota En Visual Studio 2005, haga clic con el botón secundario en el proyecto en Explorador de soluciones y, a continuación, haga clic en Agregar o módulo .
  6. Elimine todo el código que se genera de forma predeterminada y, a continuación, pegue el código siguiente en Module2:
    Option Explicit On 
    Option Strict On
    
    Imports System
    Imports System.Threading
    
    Module Module2
        Private rwl As New ReaderWriterLock()
        Private myNumber As Long
    
        Public Property Number() As Long
            Get
                'Acquire a Read lock on the resource.
                rwl.AcquireReaderLock(Timeout.Infinite)
                Try
                    Console.WriteLine("Thread:{0} starts getting the Number", Thread.CurrentThread.GetHashCode)
                    Thread.Sleep(50)
                    Number = myNumber
                    Console.WriteLine("Thread:{0} got the Number", Thread.CurrentThread.GetHashCode)
                Finally
                    'Release the lock.
                    rwl.ReleaseReaderLock()
                End Try
            End Get
    
            Set(ByVal Value As Long)
                'Acquire a Write lock on the resource.
                rwl.AcquireWriterLock(Timeout.Infinite)
                Try
                    Console.WriteLine("Thread: {0} start writing the Number", Thread.CurrentThread.GetHashCode)
                    Thread.Sleep(50)
                    myNumber = Value
                    Console.WriteLine("Thread: {0} written the Number", Thread.CurrentThread.GetHashCode)
                Finally
                    'Release the lock.
                    rwl.ReleaseWriterLock()
                End Try
            End Set
        End Property
    End Module
    
    						
  7. Compilar el proyecto y ejecútelo.

Cómo crear una clase segura para subprocesos

Varios subprocesos pueden intentar el acceso a un objeto al mismo tiempo. Cuando más de un subproceso compite simultáneamente por acceso a un objeto, es posible que algunos subprocesos pueden obtener un estado no válido si otro subproceso modifica el recurso al mismo tiempo. Por ejemplo, si un subproceso lee el campo del objeto mientras otro subproceso está modificando el campo, el primer subproceso puede obtener un estado no válido del campo. Esta situación se denomina una condición de anticipación.

Para evitar esta situación, puede proteger secciones críticas del código de condiciones de anticipación empleando bloqueos. Un bloqueo, representado por la palabra clave de Visual Basic SyncLock (instrucción), permite que un único subproceso de ejecución obtener derechos de ejecución exclusivos sobre un objeto. Los pasos de ejemplo siguiente muestran bloqueos:
  1. Abra Visual Studio NET..
  2. En el menú archivo , haga clic en Nuevo proyecto .
  3. En la vista de árbol de la izquierda, seleccione Visual Basic y a continuación, seleccione Aplicación de consola en la vista lista de la derecha. Presione ENTRAR.
  4. Module1 se genera automáticamente. Elimine todo el código de Module1 y, a continuación, pegue el código siguiente en Module1:
    Option Explicit On 
    Option Strict On
    
    Imports System
    Imports System.Threading
    
    Module Module1
        Public WorkItemNum As Integer = 20
        Public Done As New AutoResetEvent(False)
    
        Sub Main()
            Dim threadNum As Integer
            Dim AStudent As New Student()
    
            'Queue up 20 work items in the ThreadPool.
            For threadNum = 0 To WorkItemNum - 1
                ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf AccessClassResource), AStudent)
            Next threadNum
    
            Done.WaitOne()
    
            Console.WriteLine("All operations have completed. Press enter to exit")
            Console.ReadLine()
        End Sub
    
        Sub AccessClassResource(ByVal state As Object)
            Dim rnd As New Random()
            Dim theName As String
            Dim AStudent As Student = CType(state, Student)
    
            If rnd.Next Mod 2 <> 0 Then             'Do some thing with the static member: TeacherName.
                If rnd.Next Mod 2 <> 0 Then  'write to the TeacherName.
                    Select Case rnd.Next Mod 3
                        Case 0
                            Student.TeacherName = "Tom"
                        Case 1
                            Student.TeacherName = "Mike"
                        Case 2
                            Student.TeacherName = "John"
                    End Select
                Else 'read the static member.
                    theName = Student.TeacherName
                End If
            Else   'Do something with the instance member.
                If rnd.Next Mod 2 <> 0 Then  'write to the instance member.
                    Select Case rnd.Next Mod 3
                        Case 0
                            AStudent.SetName("Janet")
                        Case 1
                            AStudent.SetName("David")
                        Case 2
                            AStudent.SetName("Ben")
                    End Select
                Else 'read the instance member.
                    theName = AStudent.GetName()
                End If
            End If
    
            'Because it is possible that multiple threads may access the WorkItemNum, 
            'you must use the Interlocked.Decrement to decrease it.
            If Interlocked.Decrement(WorkItemNum) = 0 Then
                'Set the event to notify the main thread that all work is completed.
                Done.Set()
            End If
        End Sub 'AccessClassResource
    End Module
    
    					
  5. Haga clic con el botón secundario en el proyecto en Explorador de soluciones y, a continuación, haga clic en Agregar o Agregar clase . Agregar Class1.vb al proyecto.

    Nota En Visual Studio 2005, haga clic con el botón secundario en el proyecto en Explorador de soluciones y, a continuación, haga clic en Agregar o clase .
  6. Elimine todo el código que se genera de forma predeterminada y, a continuación, pegue el código siguiente en Class1.vb:
    Option Explicit On 
    Option Strict On
    
    Imports System
    Imports System.Threading
    
    Public Class Student
        Private Shared myTeacherName As String = "Bill"
        Private myName As String = "Grace"
    
        Public Shared Property TeacherName() As String
            Get
                Dim theName As String
    
                SyncLock GetType(Student) 'Synchronize access to the shared member.
                    Console.WriteLine("Thread {0} starts to get the teacher's name", Thread.CurrentThread.GetHashCode)
                    theName = myTeacherName
                    'Wait for 0.3 second.
                    Thread.Sleep(300)
                    Console.WriteLine("Thread {0} finished to get the teacher's name:{1}.", Thread.CurrentThread.GetHashCode, theName)
                End SyncLock
    
                Return theName
            End Get
            Set(ByVal Value As String)
                SyncLock GetType(Student) 'Synchronize access to the shared member.
                    Console.WriteLine("Thread {0} starts to set the teacher's name.", Thread.CurrentThread.GetHashCode)
                    myTeacherName = Value
                    'Wait for 0.3 second.
                    Thread.Sleep(300)
                    Console.WriteLine("Thread {0} finished to set the teacher's name:{1}.", Thread.CurrentThread.GetHashCode, Value)
                End SyncLock
            End Set
        End Property
    
        Public Function GetName() As String
            Dim theName As String
    
            SyncLock Me 'Synchronize access to the shared member.
                Console.WriteLine("Thread {0} starts to get the student's name.", Thread.CurrentThread.GetHashCode)
                theName = myName
                'Wait for 0.3 second.
                Thread.Sleep(300)
                Console.WriteLine("Thread {0} finished to get the student's name:{1}", Thread.CurrentThread.GetHashCode, theName)
    
                Return theName
            End SyncLock
        End Function
    
        Public Function SetName(ByVal NewName As String) As String
            Dim theOldName As String
    
            SyncLock Me 'Synchronize access to the shared member.
                Console.WriteLine("Thread {0} starts to set the student's name.", Thread.CurrentThread.GetHashCode)
                theOldName = myName
                myName = NewName
                'Wait for 0.3 second.
                Thread.Sleep(300)
                Console.WriteLine("Thread {0} finished to set the student's name:{1}", Thread.CurrentThread.GetHashCode, NewName)
            End SyncLock
    
            Return theOldName
        End Function
    End Class
    
    					
  7. Compilar el proyecto y ejecútelo.

Referencias

Para obtener más información acerca de este tema, consulte los siguientes sitios Web de MSDN de Microsoft:
Thread Pooling
ReaderWriterLock Concepts
ReaderWriterLock Class

Propiedades

Id. de artículo: 316136 - Última revisión: lunes, 24 de febrero de 2014 - Versión: 3.3
La información de este artículo se refiere a:
  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition
Palabras clave: 
kbnosurvey kbarchive kbmt kbvs2005swept kbvs2005applies kbhowtomaster KB316136 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 316136

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com