domingo, septiembre 10, 2006

Problema con Thread en vb.net 2005

SOLUCIÓN PROPUESTA

Estimado Javier:

Me encanta el cuestionamiento que haces en tu primera pregunta, ya que efectivamente es un error simplemente quitarle al control que haga la revisión de llamadas cruzadas entre hilos de manera ilegal. Yo particularmente no lo haría y mas bien implementaría un par de cambios a tu código que permitirían realizar la llamada de manera segura.

Pero antes déjame comentarte que es lo que esta pasando. Cuando utilizas mas de un hilo a la vez y estos manipulan el estado de un control es probable que se presente una inconsistencia en el estado del control provocado porque el mismo control puede ser modificado por los dos hilos al mismo tiempo.

Y es por eso que a partir del framework 2.0 cuando tu estas ejecutando tu aplicación en el debbuger y un hilo diferente al que creo el control intenta llamar al mismo el framework te avisa que se esta haciendo la llamada de manera no segura enviándote un error del tipo InvalidOperationException con el fin de que puedas identificarlo para corregirlo y que no te suceda con la aplicación ya trabajando en tiempo de ejecución.

Para corregir esto lo que tienes que hacer es verificar si la llamada que esta tratando de realizar la operación sobre el control es ejecutada desde el mismo hilo que lo creo y en caso contrario deberás hacer una llamada asíncrona por medio de un delegado invocando al mismo por medio del hilo del formulario que creo el objeto.
Pero como todo esto que te acabo de comentar suena un poco complicado voy a aplicar la solución a tu código para que lo puedas ver mas claramente.

CodigoProblemaConThread.txt


Imports System.Threading

Public Class Form1
'Se agrego un delegado que sera el que se
'encarge de la llamada asíncrona que agregue
'el ítem a la lista
Delegate Sub AddItemCallBack _
(ByVal Item As Integer)
Private Sub Button1_Click _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim obj_multi As New Thread _
(AddressOf llenar)
obj_multi.Start()
End Sub
Private Sub llenar()
Dim cont As Integer
For cont = 0 To 100
'En lugar de llamar directamente al
'ListBox vamos a ejecutar
'un método de la clase llamado
'AddItemToLista
Me.AddItemToList(cont)
'ListBox1.Items.Add(cont)
Next
End Sub

'Este método demuestra un patrón para realizar
'llamadas seguras a hilos
'en un control Windows Forms.
'Si el hilo que hace la llamada es diferente
'que el hilo que creo el control
'ListBox, entonces el método crea un
'AddItemCallBack y lo manda llamar desde
'el mismo de manera asíncrona utilizando en
'método invoke.
'Si el hilo es el mismo que el que creo el
'control ListBox, entonces el Ítem
' es agregado directamente
Public Sub AddItemToList(ByVal Item As Integer)
If Me.ListBox1.InvokeRequired Then
Dim d As New AddItemCallBack _
(AddressOf AddItemToList)
Me.Invoke(d, New Object() {Item})
Else
ListBox1.Items.Add(Item)
End If

End Sub

End Class


Espero sinceramente que la información te sea de utilidad.

Atentamente,
Raúl Guerrero
http://www.superneurona.com


MENSAJE ORIGINAL


"Javier Muñoz" wrote:

> Tengo el siguiente problema, que aparece en un post anterior, pero que no me da una solucion satisfactoria.
> tengo el siguiente codigo demo:
>
>
> Imports System.Threading
>
> Public Class Form1
>
>
>
> Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
>
> Dim obj_multi As New Thread(AddressOf llenar)
>
> obj_multi.Start()
>
> End Sub
>
>
>
>
>
> Private Sub llenar()
>
> Dim cont As Integer
>
> For cont = 0 To 100
>
> ListBox1.Items.Add(cont)
>
> Next
>
> End Sub
>
>
>
> End Class
>
> y me da el siguiente error:
>
> Message="Operación no válida a través de subprocesos: Se tuvo acceso al control 'ListBox1' desde un subproceso distinto a aquel en que lo creó."
>
> en el post anterior se desia que se podia remediar colocando siguiente valor en el LOAD del formulario
> Control.CheckForIllegalCrossThreadCalls = False
> pero mi duda y preocupacion es la siguiente.
> 1.- Si el Frameworks 2.0 trabaja asi, tiene que ser por alguna razon, y si coloco este codigo el sistema corre el riesgo de crear un fallo, o me equivoca ?
> 2.- Como tendria que hacerlo para seguir las reglas de frameworks 2.0, para realizar esta operacion ??
> desde ya, muchas gracias por su ayuda

REFERENCIA AL GRUPO DE NOTICIAS:
http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.es.dotnet.vb&mid=b1332745-8dfc-493d-b7e8-6347613144ca