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

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Acceso a un controlador desde otro hilo ?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Acceso a un controlador desde otro hilo ?  (Leído 4,072 veces)
kondrag_X1

Desconectado Desconectado

Mensajes: 157


Ver Perfil
Acceso a un controlador desde otro hilo ?
« en: 3 Abril 2015, 16:11 pm »

Buenas ya  se que esta pregunta es genérica y básica pero yo quiero centrarme en la eficiencia y cual es más fácil de entender cuando se relee el código.

en este link podeis encontrar las diferencias:
http://www.elguille.info/NET/vs2005/trucos/acceder_a_un_control_desde_otro_hilo.htm

mi cuestión es que he descubierto otra forma y me gustaría una opinion a ver cual les parece más clara y si sabrían decirme a nivel de eficiencia cual es la mejor.

mi forma

Código:
string mensaje = "";
            if(InvokeRequired)
            {
                Invoke(new Action(() => mensaje += combobox.SelectedItem));
             }
como se ve en este caso se utiliza una función lamba.


En línea

Eleкtro
Ex-Staff
*
Conectado Conectado

Mensajes: 9.878



Ver Perfil
Re: Acceso a un controlador desde otro hilo ?
« Respuesta #1 en: 3 Abril 2015, 18:38 pm »

¿A que diferencia te refieres exactamente?.

En ambos códigos el tuyo y el de aquella url se llama al mismo método 'Windows.Forms.Control.InvokeRequired' y 'Windows.Forms.Control.Invoke', le pasas el delegado y al compilar se generan las mismas instrucciones IL que internamente determinan lo mismo, hallar el handle del control/form para descubrir a que thread pertenece.

No hay diferencia alguna en lo que se refiere a eficiencia, tampoco por que le pases un delegado con la referencia del método o una expresión lambda.

Ahora, deberías seguir los ejemplos de buenos hábitos, es decir, invocar el control y no el form (aunque eso no afecta para nada al rendimiento pero puede resultar en confusión), y ademas añadir una verificación antes de invocarlo:

Ejemplo en VB.Net
Código
  1. Dim msg As String = "" & ComboBox1.SelectedItem() ' No es necesario invocar para leer.
  2.  
  3. Select Case Me.TextBox1.InvokeRequired
  4.  
  5.  Case True ' Invoco para modificar la propiedad.
  6.      Me.TextBox1.Invoke(Sub() Me.TextBox1.Text = msg)
  7.  
  8.  Case Else
  9.      Me.TextBox1.Text = msg
  10.  
  11. End Select

Traducción online a C#:
Código
  1. string msg = "" + ComboBox1.SelectedItem(); // No es necesario invocar para leer.
  2.  
  3. switch (this.TextBox1.InvokeRequired) {
  4.  
  5. case true: // Invoco para modificar la propiedad.
  6. this.TextBox1.Invoke(() => this.TextBox1.Text == msg);
  7. break;
  8.  
  9. default:
  10. this.TextBox1.Text = msg;
  11. break;
  12. }

Si quieres reducir el código para no tener que estar escribiendo siempre lo mismo, puedes desarrollar un método genérico cómo este:

Código
  1.    ''' <remarks>
  2.    ''' *****************************************************************
  3.    ''' Snippet Title: Control Invoker
  4.    ''' Code's Author: Elektro
  5.    ''' Date Modified: 03-April-2015
  6.    ''' Usage Example:
  7.    ''' ControlInvoker(TextBox1, Sub(tb) tb.Text = "Hello World!")
  8.    '''
  9.    ''' ControlInvoker(TextBox1, Sub(tb As TextBox)
  10.    '''                              For x As Integer = 0 To 5
  11.    '''                                  tb.AppendText(CStr(x))
  12.    '''                              Next x
  13.    '''                          End Sub)
  14.    ''' *****************************************************************
  15.    ''' </remarks>
  16.    ''' <summary>
  17.    ''' Executes an encapsulated method on the thread that owns the specified control.
  18.    ''' </summary>
  19.    ''' <typeparam name="T"></typeparam>
  20.    ''' <param name="ctrl">The control to invoke.</param>
  21.    ''' <param name="method">The encapsulated method to be called.</param>
  22.    Public Sub ControlInvoker(Of T As Control)(ByVal ctrl As T, ByVal method As Action(Of T))
  23.  
  24.        If ctrl.InvokeRequired Then
  25.            ctrl.Invoke(New Action(Of T, Action(Of T))(AddressOf ControlInvoker), ctrl, method)
  26.  
  27.        Else
  28.            method(ctrl)
  29.  
  30.        End If
  31.  
  32.    End Sub

Traducción online a C#:
Código
  1. /// <remarks>
  2. /// *****************************************************************
  3. /// Snippet Title: Control Invoker
  4. /// Code's Author: Elektro
  5. /// Date Modified: 03-April-2015
  6. /// Usage Example:
  7. /// ControlInvoker(TextBox1, Sub(tb) tb.Text = "Hello World!")
  8. ///
  9. /// ControlInvoker(TextBox1, Sub(tb As TextBox)
  10. ///                              For x As Integer = 0 To 5
  11. ///                                  tb.AppendText(CStr(x))
  12. ///                              Next x
  13. ///                          End Sub)
  14. /// *****************************************************************
  15. /// </remarks>
  16. /// <summary>
  17. /// Executes an encapsulated method on the thread that owns the specified control.
  18. /// </summary>
  19. /// <typeparam name="T"></typeparam>
  20. /// <param name="ctrl">The control to invoke.</param>
  21. /// <param name="method">The encapsulated method to be called.</param>
  22.  
  23. public void ControlInvoker<T>(T ctrl, Action<T> method) where T : Control
  24. {
  25. if (ctrl.InvokeRequired) {
  26. ctrl.Invoke(new Action<T, Action<T>>(ControlInvoker), ctrl, method);
  27.  
  28. } else {
  29. method(ctrl);
  30.  
  31. }
  32.  
  33. }

Ejemplos de uso en VB.Net
Código
  1. ControlInvoker(TextBox1, Sub(tb) tb.Text = "Hello World!")

Código
  1. ControlInvoker(TextBox1, Sub(tb As TextBox)
  2.                          For x As Integer = 0 To 5
  3.                              tb.AppendText(CStr(x))
  4.                          Next x
  5.                      End Sub)

Traducción online a C#:
Código
  1. ControlInvoker(TextBox1, tb => tb.Text == "Hello World!");

Código
  1. ControlInvoker(TextBox1, (TextBox tb) =>
  2. {
  3. for (int x = 0; x <= 5; x++) {
  4. tb.AppendText(Convert.ToString(x));
  5. }
  6. })

Saludos.


« Última modificación: 3 Abril 2015, 18:56 pm por Eleкtro » En línea



kondrag_X1

Desconectado Desconectado

Mensajes: 157


Ver Perfil
Re: Acceso a un controlador desde otro hilo ?
« Respuesta #2 en: 5 Abril 2015, 17:09 pm »

Hola,

muchísimas gracias por tu respuesta, si no entiendo mal la clase Invokerequired e Invoke es lo mismo. Mi pregunta ahora es: El hecho de usar delegados para esta tarea facilita la compresensión del código? Es decir, de los dos métodos el de la página y el mío ¿Cual te costaría menos entender?

saludos.
En línea

Eleкtro
Ex-Staff
*
Conectado Conectado

Mensajes: 9.878



Ver Perfil
Re: Acceso a un controlador desde otro hilo ?
« Respuesta #3 en: 5 Abril 2015, 17:54 pm »

si no entiendo mal la clase Invokerequired e Invoke es lo mismo.
Para nada, quizás me interpretaste mal, la propiedad InvokeRequired simplemente determina si es necesario llamar al método Invoke (éste comprueba si el control se encuentra en un hilo diferente al actual), y el método Invoke hace el resto, realiza la invocación.

Si invocas repetidamente el control desde el hilo que lo creó sin realizar el chequeo con InvokeRequired entonces producirá una (muy ínfima) disminuición de rendimiento.
 
Si estás seguro de que el control siempre va a ser invocado desde un hilo distinto al que lo creó entones no es necesario realizar el chequeo con InvokeRequired pero tampoco está de más conservar los buenos hábitos añadiendo el chequeo.

Mi pregunta ahora es: El hecho de usar delegados para esta tarea facilita la compresensión del código? Es decir, de los dos métodos el de la página y el mío ¿Cual te costaría menos entender?

Hombre... creo que la comprensión del código depende de las circunstancias y de los gustos de cada uno.

Pongo cómo ejemplo este código:
Código:
sub()
    Me.TextBox1.Invoke(Sub() Me.TextBox1.Text = msg)
end sub

En mi opinión no es muy correcto tener un método encapsulado en otro método, pero usar una expresión lamdba ahí a mi me resulta más comprensible que crear el delegado y defnir un método adicional en otra parte del código, por que solamente estoy modificando una propiedad en ese ejemplo y además se que no hay lugar a ninguna posible excepción cross-thread o de otro tipo.

Al invocar, yo utilizaría los delegados para reemplazar a una expresión lambda en caso de que tuviese que realizar varias operaciones o en caso de que no estuviese del todo seguro de si pueden producirse excepciones entonces las controlaría en el método del delegado en lugar de en el bloque del lambda por que demasiadas isntrucciones quedaría bastante feo y además el lambda es un método anónimo.

Saludos!
« Última modificación: 5 Abril 2015, 17:58 pm por Eleкtro » En línea



Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines