Duda con Thread ?

Iniciado por TrashAmbishion, 21 Agosto 2016, 18:50 PM

0 Miembros y 1 Visitante están viendo este tema.

TrashAmbishion

Hola,

Leyendo este tema

http://foro.elhacker.net/net/iquesthacer_una_pausa_a_un_backgrounworker_en_vbnet-t405073.0.html;msg1906376

Me surge algunas dudas cuando trato de aplicarlo en mi proyecto.

Tengo un sub que verifica los procesos que estan corriendo en el Pc:

Tendría que quedar así supongo..

Código (vbnet) [Seleccionar]
Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) _
   Handles MyWorker.DoWork

       Do While MyWorker.CancellationPending = False
               
               _busy.WaitOne(5000)        'Creo un intervalo de 5 segundos para ejecutar el Sub
               CheckProcess()

       Loop

       e.Cancel = True

   End Sub



Tengo otro sub que igual verifica los módulos de una aplicación que supongo tendria que hacer otro backgroundworker

z3nth10n

¿Y cuál es la duda en concreto? Porque yo no he visto que hayas preguntado nada. Solamente, has puesto código, y lo has puesto mal.

Un saludo.

Interesados hablad por Discord.

TrashAmbishion

Pues busco saber si estoy por el camino correcto..

Si te distes cuenta modifique el código original porque necesito que el Loop no se detenga a menos que se haga true la cancelación...


Eleкtro

#3
Cita de: TrashAmbishion en 21 Agosto 2016, 18:59 PMnecesito que el Loop no se detenga a menos que se haga true la cancelación...

Si es una necesidad del tipo "hasta que..." en vez de "mientras que...", entonces puedes hacer el código algo más comprensible de la siguiente manera:

Código (vbnet) [Seleccionar]
Do Until MyWorker.CancellationPending
   ...
Loop





Cita de: TrashAmbishion en 21 Agosto 2016, 18:50 PMMe surge algunas dudas cuando trato de aplicarlo en mi proyecto.

Para hacer una pausa (o dicho de otra forma: bloquear la ejecución del hilo actual) durante un intervalo definido (ej. 5 segundos) debes utilizar el método System.Threading.Thread.Sleep():

Código (vbnet) [Seleccionar]
Sleep(TimeSpan.FromSeconds(5))
CheckProcess()


El uso que le doy a la class ManualResetEvent es para implementar una funcionalidad de pausar/continuar a demanda o petición del usuario, puesto que el método ManualResetEvent.WaitOne() sirve para bloquear la ejecución del thread durante un tiempo indefinido hasta que se reciba una señal llamando a ManualResetEvent.Set(), por eso si te fijas en mi ejemplo uso la constante de tiempo infinito System.Threading.Timeout.Infinite.

Si tu especificas 5000 ms en el parámetro del método ManualResetEvent.WaitOne(), con eso le estás diciendo que el hilo debe esperar hasta que transcurra ese intervalo de tiempo definido o hasta recibir una señal durante ese tiempo, y si no recibe una señal durante ese tiempo se resumirá el hilo, esto quiere decir que le estás dando la misma funcionalidad que si utilizases el método System.Threading.Thread.Sleep(), pero no debes hacerlo, primeramente por que es innecesario, segundo por que es de buena costumbre utilizar el método más apropiado para "X" finalidad y en este caso el método System.Threading.Thread.Sleep() es el que ha sido diseñado para dicha finalidad, y tercero por que podría ocasionarte un comportamiento indebido por culpa de un fallo de lógica humana, por ejemplo si enviases una señal en otra parte del código durante ese intervalo de tiempo.




Cita de: TrashAmbishion en 21 Agosto 2016, 18:50 PMTengo otro sub que igual verifica los módulos de una aplicación que supongo tendria que hacer otro backgroundworker

Depende del propósito del código, pero ya estás corriendo la tarea de la "verificación de procesos" en un hilo secundario ...puedes llevar a cabo la "verificación de módulos" de forma sincrónica si eso no te suponiese inconvenientes.

Saludos!








TrashAmbishion

Gracias aclarada la duda es que en aquel tema pusiste el ejemplo pero no tenia bien claro el funcionamiento de esa función por el tema de los señales que me tenían inquieto..

Ok voy acomodarlo en el mismo Sub para ver como rula..

Una duda en el Form principal tengo 2 objetos un txt y un combo, para consultar el contenido de ambos desde una clase yo lo hacía:

frmprincipal.txtusername.text

Lo ideal seria que guardase estos valores en una clase que contenga esos parametros, cierto ?

Eleкtro

Cita de: TrashAmbishion en 21 Agosto 2016, 20:37 PMUna duda en el Form principal tengo 2 objetos un txt y un combo, para consultar el contenido de ambos desde una clase yo lo hacía:

frmprincipal.txtusername.text

Lo ideal seria que guardase estos valores en una clase que contenga esos parametros, cierto ?

No se si he llegado a entender bien lo que quieres conseguir, pero si tienes un TextBox que muestra unos datos los cuales luego necesitas leer desde otra class, entonces puedes seguir haciendo eso.

Si necesitases evitar conflictos entre threads entonces también podrías declarar una variable compartida y asignarle el valor cada vez que se modifica el texto del TextBox:

Código (vbnet) [Seleccionar]
Class Class1
    Friend Shared Username As String

    Friend TextBox1_TextChanged(sender As Object, e As Eventargs) Handles TextBox1.TextChanged
        Class1.Username = DirectCast(sender, TextBox).Text
    End Sub
End Class1


Código (vbnet) [Seleccionar]
Class Class2
   ...
   MsgBox(Class1.Usrname)
   ...
End Class2


Si necesitases leer múltiples objetos/valores desde la otra class, entonces definir un tipo personalizado para almacenar esos datos como tu dijiste sería ideal. También podrías serializar el tipo/clase en un archivo local.

Saludos








TrashAmbishion

Ok lo tendré en cuenta, se me pasaba otra duda...

En el funcionamiento del Sub existirá el momento en que por ejemplo los modulos incrementen o se produzca un error y quisiera manejarlo...

Esto tendria que hacerlo con un raiseevent cierto ??

Salu2

Eleкtro

#7
Cita de: TrashAmbishion en 21 Agosto 2016, 21:03 PMEn el funcionamiento del Sub existirá el momento en que por ejemplo los modulos incrementen o se produzca un error y quisiera manejarlo...

Esto tendria que hacerlo con un raiseevent cierto ??

Los errores se controlan con bloques try/catch:
Código (vbnet) [Seleccionar]
Declaración de objetos...

Try
   Instanciación de objetos...
   Sentencias de procesos/modulos...

Catch ex As (Tipo De Excepción) ' When (Condición)
   Informar de ex.Message

Finally
   Liberación de objetos declarados.

End Try

( el bloque Finally es opcional en caso de que no uses objetos "disposables" )

Ahora, suponiendo que hayas declarado un evento en tu código entonces por supuesto puedes disparar ese evento con RaiseEvent cuando controles un error  ...pero yo diría que no es lo que realmente preguntas.

Saludos








TrashAmbishion

Hola,

Por suerte se del Try y lo uso en casi todos los procedimientos y funciones a menos que sea algo muy simple.

Me explico mejor, en el Form principal tengo esta declaración:

Dim WithEvents Client_Conn as Winsock

Lo que pretendía en la clase BackgroundWorker era que cuando se produjera un error específico, este lo manejara usando el evento Enviar de e Client_Conn

Lo resolví

FormPrinc.Client_Conn.Enviar("Mensaje")

Esto lo hice por lo que me habías dicho anteriormente...

Cuando no debo usar esta forma...

Esto es aparte cuando yo llamo al Sub Cancel del Worker, en el DoWork se debe hacer TRUE el CancellationPending...

Código (vbnet) [Seleccionar]
    Class Class1
        Friend Shared Username As String
     
        Friend TextBox1_TextChanged(sender As Object, e As Eventargs) Handles TextBox1.TextChanged
            Class1.Username = DirectCast(sender, TextBox).Text
        End Sub
    End Class1


Esto sería en el Form principal o en la clase donde voy a guardar los valores de esos Text, lo digo por el evento Text_Changed que asumo deba estar en el Form principal...

Salu2