elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Los controles de la class principal no se actualizan con delegados... :-/
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Los controles de la class principal no se actualizan con delegados... :-/  (Leído 3,557 veces)
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.817



Ver Perfil
Los controles de la class principal no se actualizan con delegados... :-/
« en: 20 Diciembre 2012, 14:05 pm »

Es la primera vez que pruebo a hacer esto y no se que error estoy comentiendo...

Por un lado tengo la class principal (Form1)
Por otro lado tengo una class para un backgroundworker

Al usar delegados desde la segunda class para modificar la propiedad de un control de la class principal no sucede nada, la propiedad se modifica pero el control no se actualiza visualmente hablando en el form...  es decir, ni el label ni la progressbar cambian de estado :¬¬


class principal.vb :
Código
  1. Public Randomize_thread As New Randomize_thread_class
  2. ...
  3. Randomize_thread.StartBackgroundTask()
  4. ...


class del backgroundworker.vb :
Código
  1.  
  2. Imports PlayLists.Form1
  3.  
  4. ...
  5.  
  6.    Public WithEvents Randomize_thread As New BackgroundWorker
  7.  
  8.    Public Sub InvokeControl(Of T As Control)(ByVal Control As T, ByVal Action As Action(Of T))
  9.        If Control.InvokeRequired Then
  10.            Control.Invoke(New Action(Of T, Action(Of T))(AddressOf InvokeControl), New Object() {Control, Action})
  11.        Else
  12.            Action(Control)
  13.        End If
  14.    End Sub
  15.  
  16. ...
  17.  
  18.    Public Sub Randomize_thread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles Randomize_thread.DoWork
  19.        Dim lines = File.ReadAllLines(PlayLists.Form1.Temp_file)
  20.        Dim nLines = lines.Count
  21.        Dim randomNumbers = RandomList(nLines)
  22.        Dim tmpFile = Path.GetTempFileName()
  23.  
  24.        InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Visible = True)
  25.        InvokeControl(PlayLists.Form1.ProgressBar1, Sub(x) x.Maximum += nLines)
  26.        Using sw = New StreamWriter(tmpFile, False, Encoding.UTF8)
  27.            For i = 0 To nLines - 1
  28.                sw.WriteLine(lines(randomNumbers(i)))
  29.                InvokeControl(PlayLists.Form1.ProgressBar1, Sub(x) x.Value = i)
  30.                InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Text = "Randomizing " + i.ToString() + " of " + (nLines - 1).ToString() + " files.")
  31.                ' InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Refresh())
  32.                ' InvokeControl(PlayLists.Form1.ProgressBar1, Sub(x) x.Refresh())
  33.            Next
  34.        End Using
  35.        InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Text = "All files launched")
  36.    End Sub


« Última modificación: 20 Diciembre 2012, 14:25 pm por EleKtro H@cker » En línea

Novlucker
Ninja y
Colaborador
***
Desconectado Desconectado

Mensajes: 10.683

Yo que tu lo pienso dos veces


Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #1 en: 20 Diciembre 2012, 14:23 pm »

Desde el DoWork debes de invocar al método ReportProgress. Luego desde el evento ProgressChanged del BackgroundWorker realizas las modificaciones necesarias.

http://msdn.microsoft.com/es-es/library/system.componentmodel.backgroundworker.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

Saludos


En línea

Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD
"Hay dos cosas infinitas: el Universo y la estupidez  humana. Y de la primera no estoy muy seguro."
Albert Einstein
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.817



Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #2 en: 20 Diciembre 2012, 15:56 pm »

Vale Nov, lo he intentado así

Código
  1. sub dowork(...)
  2. ...
  3. Using sw = New StreamWriter(tmpFile, False, Encoding.UTF8)
  4.            For filei = 0 To nLines - 1
  5.                sw.WriteLine(lines(randomNumbers(filei)))
  6.                Randomizethread.ReportProgress(filei)
  7.            Next
  8.        End Using
  9. ...
  10. end sub

Código
  1.    Public Shared Sub Randomizethread_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles Randomizethread.ProgressChanged
  2.        ' Thread.Sleep(300)
  3.        InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Text = "Randomizing " + filei.ToString() + " of " + (nlines - 1).ToString() + " files.")
  4.    End Sub


Problema: Sigue sin actualizarse el label (ni cualquier otro elemento al que llame, como la barra de progreso por ejemplo vaya) :¬¬ :¬¬ :¬¬

Ni con un refresh() puedo.

EDITO: El label se actualiza cuando el hilo se completa (cuando sucede el evento del workercompleted), asi que me imagino que el culpable es el FOR?, ¿Como puedo solucionarlo?

PD: No creo que séa problema del delegado porque si compruebo el valor con un msgbox(PlayLists.Form1.progresslabel.txt) veo que el valor es correcto
« Última modificación: 20 Diciembre 2012, 16:11 pm por EleKtro H@cker » En línea

Keyen Night


Desconectado Desconectado

Mensajes: 496


Nothing


Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #3 en: 20 Diciembre 2012, 19:38 pm »

Cuando realizas operaciones asincrónicas normalmente no solo es una ProgressBar la que advierte cambios a veces tenemos Label que muestran información y otros controles los cuales necesitamos modificar mientras la operación va avanzando, la forma más sencilla es usar el segundo parámetro del método ReportProgress, este es UserState, puedes crear una estructura que almacene todos los datos que necesitas pasarle al evento ProgressChanged el los recibe a través de e.UserState, es bastante sencillo y cómodo ;)
En línea

La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...
spiritdead

Desconectado Desconectado

Mensajes: 296


Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #4 en: 20 Diciembre 2012, 19:41 pm »

Es la primera vez que pruebo a hacer esto y no se que error estoy comentiendo...

Por un lado tengo la class principal (Form1)
Por otro lado tengo una class para un backgroundworker

Al usar delegados desde la segunda class para modificar la propiedad de un control de la class principal no sucede nada, la propiedad se modifica pero el control no se actualiza visualmente hablando en el form...  es decir, ni el label ni la progressbar cambian de estado :¬¬


class principal.vb :
Código
  1. Public Randomize_thread As New Randomize_thread_class
  2. ...
  3. Randomize_thread.StartBackgroundTask()
  4. ...


class del backgroundworker.vb :
Código
  1.  
  2. Imports PlayLists.Form1
  3.  
  4. ...
  5.  
  6.    Public WithEvents Randomize_thread As New BackgroundWorker
  7.  
  8.    Public Sub InvokeControl(Of T As Control)(ByVal Control As T, ByVal Action As Action(Of T))
  9.        If Control.InvokeRequired Then
  10.            Control.Invoke(New Action(Of T, Action(Of T))(AddressOf InvokeControl), New Object() {Control, Action})
  11.        Else
  12.            Action(Control)
  13.        End If
  14.    End Sub
  15.  
  16. ...
  17.  
  18.    Public Sub Randomize_thread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles Randomize_thread.DoWork
  19.        Dim lines = File.ReadAllLines(PlayLists.Form1.Temp_file)
  20.        Dim nLines = lines.Count
  21.        Dim randomNumbers = RandomList(nLines)
  22.        Dim tmpFile = Path.GetTempFileName()
  23.  
  24.        InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Visible = True)
  25.        InvokeControl(PlayLists.Form1.ProgressBar1, Sub(x) x.Maximum += nLines)
  26.        Using sw = New StreamWriter(tmpFile, False, Encoding.UTF8)
  27.            For i = 0 To nLines - 1
  28.                sw.WriteLine(lines(randomNumbers(i)))
  29.                InvokeControl(PlayLists.Form1.ProgressBar1, Sub(x) x.Value = i)
  30.                InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Text = "Randomizing " + i.ToString() + " of " + (nLines - 1).ToString() + " files.")
  31.                ' InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Refresh())
  32.                ' InvokeControl(PlayLists.Form1.ProgressBar1, Sub(x) x.Refresh())
  33.            Next
  34.        End Using
  35.        InvokeControl(PlayLists.Form1.progresslabel, Sub(x) x.Text = "All files launched")
  36.    End Sub

no uses backgroundworker con delegados ... usa threads
En línea

Facilitador De Tareas - Task Simplifier (FDT)
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.817



Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #5 en: 21 Diciembre 2012, 06:52 am »

no uses backgroundworker con delegados ... usa threads

Si eso está muy bien pero... todos sabemos que un "System.Threading.Thread" sólamente se puede iniciar una vez,
He leido que para poder ejecutar el mismo thread infinitas veces solo hay que resetear la variable de la instancia del thread, osea crear una nueva instancia de "System.Threading.Thread" que llame al mismo thread

Por ejemplo:

Código
  1.    Sub MITHREAD()
  2.       msgbox("hello world")
  3.    End Sub
  4.  
  5. Dim T_first_instance As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  6. T_first_instance.Start()
  7.  
  8. ' esperamos a que el thread finalice y entonces lo volvemos a llamar cuando necesitemos volver a usarlo, pero creandolo con otro nombre de variable:
  9. Dim T_second_instance As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  10. T_second_instance.Start()
  11. '
  12. ' EL ADREESOF ES EL MISMO PARA LAS DOS INSTANCIAS YA QUE LA INTENCIÓN ES PODER USAR EL MISMO THREAD UNA Y OTRA VEZ.

No sé si lo hice bien, donde leí la solución para ejecutar el mismo thread las veces que uno quiera no había ningún ejemplo,
pero en caso de que el ejemplo que he dado séa correcto entonces necesito encontrar la manera de que el nombre de la variable se cree automáticamente para poder llamarlo las veces que séa necesario...
Necesitaría algo así:

Código
  1.  
  2. sub button1_clicked...
  3.       Dim RandomClass As New Random()
  4.        Dim RandomNumber As Integer = RandomClass.Next()
  5.        Dim T_(RandomNumber) As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  6.        T_(RandomNumber).Start()
  7. end sub
  8.  

Está claro que mi intento de randomizar la variable de la instancia no funciona,
¿Me pueden ayudar a hacerlo?
« Última modificación: 21 Diciembre 2012, 06:55 am por EleKtro H@cker » En línea

spiritdead

Desconectado Desconectado

Mensajes: 296


Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #6 en: 21 Diciembre 2012, 06:58 am »

Si eso está muy bien pero... todos sabemos que un "System.Threading.Thread" sólamente se puede iniciar una vez,
He leido que para poder ejecutar el mismo thread infinitas veces solo hay que resetear la variable de la instancia del thread, osea crear una nueva instancia de "System.Threading.Thread" que llame al mismo thread

Por ejemplo:

Código
  1.    Sub MITHREAD()
  2.       msgbox("hello world")
  3.    End Sub
  4.  
  5. Dim T_first_instance As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  6. T_first_instance.Start()
  7.  
  8. ' esperamos a que el thread finalice y entonces lo volvemos a llamar cuando necesitemos volver a usarlo, pero creandolo con otro nombre de variable:
  9. Dim T_second_instance As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  10. T_second_instance.Start()
  11. '
  12. ' EL ADREESOF ES EL MISMO PARA LAS DOS INSTANCIAS YA QUE LA INTENCIÓN ES PODER USAR EL MISMO THREAD UNA Y OTRA VEZ.

No sé si lo hice bien, donde leí la solución para ejecutar el mismo thread las veces que uno quiera no había ningún ejemplo,
pero en caso de que el ejemplo que he dado séa correcto entonces necesito encontrar la manera de que el nombre de la variable se cree automáticamente para poder llamarlo las veces que séa necesario...
Necesitaría algo así:

Código
  1.  
  2. sub button1_clicked...
  3.       Dim RandomClass As New Random()
  4.        Dim RandomNumber As Integer = RandomClass.Next()
  5.        Dim T_(RandomNumber) As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  6.        T_(RandomNumber).Start()
  7. end sub
  8.  

Está claro que mi intento de randomizar la variable de la instancia no funciona,
¿Me pueden ayudar a hacerlo?
al terminar el ciclo del thread no podras reiniciarlo, por lo que debes liberarlo y crear 1 nueva instancia usando el "new"

Dim T_first_instance As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
despues que trabaje simplemente harias

T_first_instance = new thread(addressOF sub/function)
y vuelves a arrancarlo ;)

y de usarles claro q se puede, :) pronto te mostrare mi motor FTP, con soporte multi-descargas paralelas

que trabaja con 1 hilo monitor y de 2-4 hilos auxiliares 1 para cada descarga o subida para subidas y descargas paralelas
En línea

Facilitador De Tareas - Task Simplifier (FDT)
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.817



Ver Perfil
Re: Los controles de la class principal no se actualizan con delegados... :-/
« Respuesta #7 en: 21 Diciembre 2012, 07:11 am »

despues que trabaje simplemente harias
T_first_instance = new thread(addressOF sub/function)
y vuelves a arrancarlo ;)

uf, perfecto lo conseguí, esto me va a ahorrar mucha comida de coco, gracias !!

Código
  1. Public thread_1 As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  2.  
  3.    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  4.        ' Cada vez que el botón séa presionado se ejecutará el mismo thread una y otra vez, oh yeah :D !!!
  5.        Dim thread_1 As System.Threading.Thread = New Threading.Thread(AddressOf MITHREAD)
  6.        thread_1.Start()
  7.    End Sub

PD: Realmente no encontraba información sobre como ejecutar el mismo thread una vez "ha muerto".
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Delegados en hilos... algo raro « 1 2 »
.NET (C#, VB.NET, ASP)
Zzombi 10 10,621 Último mensaje 7 Diciembre 2009, 00:03 am
por [D4N93R]
[Tutorial] Delegados en .Net (C#)
.NET (C#, VB.NET, ASP)
[D4N93R] 0 7,439 Último mensaje 30 Julio 2010, 17:47 pm
por [D4N93R]
[Solucionado][Duda][C#]Eventos y delegados
.NET (C#, VB.NET, ASP)
final_frontier 5 5,452 Último mensaje 17 Agosto 2010, 14:55 pm
por [D4N93R]
Delegados Generales [Aporte]
.NET (C#, VB.NET, ASP)
Keyen Night 0 1,638 Último mensaje 19 Febrero 2012, 22:59 pm
por Keyen Night
Ayuda con delegados y objetos [C#] « 1 2 »
.NET (C#, VB.NET, ASP)
Vaagish 10 5,758 Último mensaje 24 Mayo 2014, 21:10 pm
por samuelhm
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines