Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problema con Thread en vb.net 2005

22,359 views
Skip to first unread message

Javier Muñoz

unread,
Sep 9, 2006, 5:37:06 PM9/9/06
to
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.

Raul Guerrero

unread,
Sep 10, 2006, 2:22:01 AM9/10/06
to
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.
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

Seguimiento en mi blog sobre este tema:
http://help.superneurona.com/2006/09/problema-con-thread-en-vbnet-2005.html

Escucha mi podcast:
http://podcast.superneurona.com

Javier Muñoz

unread,
Sep 12, 2006, 6:47:49 PM9/12/06
to
Gracias por la ayuda.. y si funciona el codigo.
pero por dudas realiza un codigo con un timer con la hora y los
milisegundos.. probe el codigo y la hora se tendia a pegar... lo probe
desbloqueando la verificacion de los hilos y funciono sin hacer detener los
milisegundos..
voy a ver como se puede hacer para que esta funcion no afecte la velocidad
de funcionamiento del sistema.

"Raul Guerrero" <RaulGu...@discussions.microsoft.com> escribió en el
mensaje news:D96B696B-51F2-4B3B...@microsoft.com...

powerbu...@hotmail.com

unread,
Sep 4, 2012, 7:09:57 PM9/4/12
to
Muy Bueno me sirvio muxoooo :) GRACIASSSSSSSS

vazqu...@gmail.com

unread,
Dec 10, 2013, 6:23:08 PM12/10/13
to
Hola Amigo, tengo un problema similar, pero el mio es el siguiente.

Trabajo con Visual Studio 2010
Estoy trabajando con un hilo de ejecución de BackgroundWorker
y dentro del hilo tengo un grid de devExpress, la primera vez funciona bien pero la segunda me dice que "Operación no válida a través de
subprocesos" y el erro me lo da cuando pretendo agregar un datatable al Grid, así le asigno el datatable al grid: gcGrid.DataSource = dtDatos y es justamente aquí donde da el error.
Que me sugieres hacer?

angelalv...@gmail.com

unread,
Jan 3, 2014, 2:19:18 AM1/3/14
to
funciona a la perfeccion, es lo que estaba buscando, lo hice con un grid y todo bien, saludos

onoriopa...@gmail.com

unread,
Feb 20, 2014, 8:35:55 AM2/20/14
to
Excelente aportación Raul, gracias.

Daniel

unread,
Aug 2, 2015, 12:03:08 AM8/2/15
to
Hola Vazqu:

Yo tengo un problema parecido y se resume de la siguiente forma
1. Llamo a la función a través de un Hilo.
2. La función se ejecuta bien, salvo el datagridview al cual debo actualizar
para que aparezcan los nuevos valores, pero que fue iniciado en otro hilo.
Lo mismo me ocurre con un timer. Lo detengo antes de llamar al hilo y una
terminada la función (que fue solicitada por medio de ese hilo) lo inicio
nuevamente. (Eso tampoco funciona.)
3. Intentaré aplicar lo que Raúl plantea y probaré.
4. Tu sabes algo más al respecto.. He intentando varios cosas pero sin resultados..

Muchas gracias por la ayuda o información que pudieses comentar.

jxpb...@gmail.com

unread,
Jul 14, 2016, 12:08:00 PM7/14/16
to
Buenas yo tengo un porblema con un chat que estoy q hago en c# me sale el mismo error pero unaod ya lo ejecuto desde un menu

rober...@gmail.com

unread,
Oct 31, 2018, 1:30:09 PM10/31/18
to
yo tengo el error pero yo hago la llamada a un form desde

void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
{
if (spot == null)
{
spot = new frmSpotify();

spot.Show();
}
else
{
spot.Show();
spot.Opacity = 80;
spot.BringToFront();
// spot.reset_timer();
}
}
porque detecta que al subir el volumen de la pc abre un form la primera vez lo abre y luego lanza la escepcion

ovalle...@gmail.com

unread,
Dec 9, 2019, 11:06:40 AM12/9/19
to
disculpa quisiera que me ayudaran con un programa que tengo o que me manden foros que ayuden a responder este es mi codigo:

1 ro: quiero que reciba todos los datos aunque sea repetido y sin que borre el dato anterior.
2 do: quiero que no me aparezca el message box ya lo trate de borrar pero me marca error cuando hago la depuracion.

Public Class Form1

Dim StrBufferEntrada As String
Dim StrBufferSalida As String

Private Delegate Sub DelegadoAcesso(ByVal AdicionarTexto As String)

Private Sub AccesoFormPrincipal(ByVal TextoForm As String)

StrBufferEntrada = TextoForm
'---------------------------------------------------
'---------------------------------------------------
TxtDatosRecibidos.Text = StrBufferEntrada
'---------------------------------------------------
'---------------------------------------------------
End Sub

Private Sub PuertaAccesoInterrupcion(ByVal BufferIn As String)
Dim TextoInterrupcion() As Object = {BufferIn}
Dim DelegadoInterrupcion As DelegadoAcesso
DelegadoInterrupcion = New DelegadoAcesso(AddressOf AccesoFormPrincipal)
MyBase.Invoke(DelegadoInterrupcion, TextoInterrupcion)

End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
StrBufferEntrada = ""
StrBufferSalida = ""
BtnConectar.Enabled = False
BtnEnviarDatos1.Enabled = False
CmbBaud.SelectedItem = ""

End Sub

Private Sub BtnBuscarPuertos_Click(sender As Object, e As EventArgs) Handles BtnBuscarPuertos.Click
For Each PuertoDisponible As String In My.Computer.Ports.SerialPortNames
CboPuertos.Items.Add(PuertoDisponible)

Next
If CboPuertos.Items.Count > 0 Then
CboPuertos.Text = CboPuertos.Items(0)
MessageBox.Show("SELECCIONAR EL PUERTO DE TRABAJO")
BtnConectar.Enabled = True

Else
MessageBox.Show("NINGUN PUERTO ENCONTRADO")
BtnConectar.Enabled = False
BtnEnviarDatos1.Enabled = False
CboPuertos.Items.Clear()
End If

End Sub

Private Sub BtnConectar_Click(sender As Object, e As EventArgs) Handles BtnConectar.Click
If BtnConectar.Text = "CONECTAR" Then
Try

SpPuerto.BaudRate = Convert.ToInt32(CmbBaud.Text)
SpPuerto.DataBits = 8
SpPuerto.Parity = IO.Ports.StopBits.None
SpPuerto.StopBits = IO.Ports.StopBits.One
SpPuerto.PortName = CboPuertos.Text
SpPuerto.Open()

BtnConectar.Text = "DESCONECTAR"
BtnEnviarDatos1.Enabled = True

Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)

End Try

ElseIf BtnConectar.Text = "DESCONECTAR" Then
BtnConectar.Text = "CONECTAR"
BtnEnviarDatos1.Enabled = False
SpPuerto.Close()

End If
End Sub

Private Sub BtnEnviarDatos_Click(sender As Object, e As EventArgs) Handles BtnEnviarDatos1.Click
SpPuerto.DiscardOutBuffer()
StrBufferSalida = TxtEnviarDatos.Text
SpPuerto.Write(StrBufferSalida)
End Sub

Private Sub DatoRecibido(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SpPuerto.DataReceived
Dim DatoInterrupcion As String
DatoInterrupcion = SpPuerto.ReadExisting
PuertaAccesoInterrupcion(DatoInterrupcion)

StrBufferEntrada = SpPuerto.ReadExisting
MessageBox.Show(TxtDatosRecibidos.Text & StrBufferEntrada)
TxtDatosRecibidos.Text = TxtDatosRecibidos.Text + StrBufferEntrada

End Sub

Private Sub CboPuertos_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CboPuertos.SelectedIndexChanged
If BtnConectar.Text = "CONECTAR" Then
Try

With SpPuerto
.BaudRate = 9600
.DataBits = 8
.Parity = IO.Ports.StopBits.None
.StopBits = IO.Ports.StopBits.One
.PortName = CboPuertos.Text
.Open()

End With

BtnConectar.Text = "DESCONECTAR"
BtnEnviarDatos1.Enabled = True

Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)

End Try

ElseIf BtnConectar.Text = "DESCONECTAR" Then
BtnConectar.Text = "CONECTAR"
BtnEnviarDatos1.Enabled = False
SpPuerto.Close()

End If
End Sub

Private Sub TxtEnviarDatos_TextChanged(sender As Object, e As EventArgs) Handles TxtEnviarDatos.TextChanged

End Sub

Private Sub TxtDatosRecibidos_TextChanged(sender As Object, e As EventArgs)

End Sub

Private Sub CmbBaud_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CmbBaud.SelectedIndexChanged

End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Button1.Text = "ATQ1" Then
Try
Button1.Text = "ATQ0"

Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)

End Try

ElseIf Button1.Text = "ATQ0" Then
Button1.Text = "ATQ1"

End If
End Sub

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If Button3.Text = "ATE1" Then
Try
Button3.Text = "ATE0"

Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)

End Try

ElseIf Button3.Text = "ATE0" Then
Button3.Text = "ATE1"

End If
End Sub

Private Sub TxtDatosRecibidos_TextChanged_1(sender As Object, e As EventArgs) Handles TxtDatosRecibidos.TextChanged
TxtDatosRecibidos.Text = StrBufferEntrada + vbCrLf
End Sub
End Class

luiseduar...@gmail.com

unread,
May 14, 2020, 1:24:15 PM5/14/20
to
tengo un problema similar en c# a ver si me puedes ayuda.



tengo el siguiente metodo de una clase Estatica.


Task.Run(() =>
{

ModelFactory<Modelo_Empleado>.InsertNamesDGV(DGVMostrar, ModelFactory<Modelo_Empleado>.GetDisplayNames());

});


el método recibe dos parámetro el primero es un DataGridView al que le quiero hacer cambios y el segundo es una lista de cadena.

como puedes ver lo estoy ejecuantando en un hilo y me da el error
"Operación no válida a través de subprocesos: Se tuvo acceso al control '' desde un subproceso distinto a aquel en que lo creó."

el q el DataGridView no fue creado en ese hilo.


este es el codigo del metodo..


public static void InsertNamesDGV(DataGridView DGV, List<string> ListHeaderName)
{
int c = 0;

foreach (string HeaderName in ListHeaderName)
{
c++;

DGV.Columns[c].AutoSizeMode =
DataGridViewAutoSizeColumnMode.DisplayedCells;

DGV.Columns[c].HeaderText = HeaderName;

}
}

0 new messages