none
Actualizar label desde un hilo diferente (desarrollo web) RRS feed

  • Pregunta

  • Desarrollo web con visual basic 2013

    Hola, quiero desde la interfaz gráfica y desde un mismo botón lanzar el mismo proceso varias veces, pero con ciertos parámetros diferentes que se capturan desde la interfaz.

    Para esto necesito hilos, pero los hilos no tienen valor de retorno, ya que los hilos se hacen sobre  los métodos [sub] .

    Entonces según la guía de Microsoft para que un hilo me retorne un valor debo utilizar [BackgroundWorker], pero este no libera la interfaz  gráfica  para iniciar otro proceso mientras que el primero se ejecuta. Entonces pensé en pasar a un hilo el [BackgroundWorker] ...y funciona.

    El problema se presenta  cuando quiero actualizar un [label] de la interfaz a medida que lo hilos van terminando…y  no funciona. Leyendo encontré que no se puede acceder desde un hilo hijo a una propiedad del hilo padre, que para este caso es el hilo de la interfaz gráfica, para esto se debe utilizar un delegado, pero tampoco  funciona                               

    Luego pensé en que  debo refrescar la página entonces se creó el updatepanel en los cuales esta los label que quiero actualizar y actualizo el panel, pero tampoco funciona igualmente hago un update panel con javascript y no funciona,

    Hay dos botones uno crea el [BackgroundWorker], de forma directa y el otro lo asigna a un hilo El que crea el [BackgroundWorker] de forma directa si actualiza los label pero el otro no

     No sé cómo programar el comportamiento que quiero… ayuda por favor.


    <%@ Page Language="vb"  Async="true" AutoEventWireup="false" CodeBehind="WebForm2.aspx.vb" Inherits="WebApplication1.WebForm2" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
        
            <asp:Button ID="Button1" runat="server" Text="Button"  />
            <asp:HiddenField ID="HiddenField1" runat="server" />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button2" runat="server" Text="Button"  />
    
            <asp:ScriptManager ID="ScriptManager1" runat="server">
             </asp:ScriptManager>
            
                <asp:UpdatePanel ID="updatepanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
                    <ContentTemplate>
                        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
                        <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
                        <asp:Label ID="Label3" runat="server" Text="Label"></asp:Label>
                        <asp:Label ID="Label4" runat="server" Text="Label"></asp:Label>
                        </ContentTemplate>
                </asp:UpdatePanel>
            
          
        </div>
           <%-- <asp:SiteMapPath ID="SiteMapPath1" runat="server"></asp:SiteMapPath>--%>
        
    
            <script>
                //OnClientClick="return campoHiden();
                var contadorhilos = 0;
                function campoHiden() {
                    var continuar = false;
                    contadorhilos = contadorhilos + 1;
                    if (contadorhilos < 5) {
                        document.getElementById("<%= HiddenField1.ClientID%>").value = 1;
                    continuar = true;
                } else {
                    continuar = false;
                    alert("no se ppuede ejecutar mas de 5 procesos de forma simultanea");
    
                }
    
                return continuar;
            }
                //OnClientClick="return recargar();" 
                function recargar() {
                 
                    __doPostBack('<%=updatepanel1.ClientID%>', '');
                    alert("hola");
                //location.reload();
                return false;
            }
    
    
            </script>
        </form>
    </body>
    
    </html>
        
    
    

    Imports System.ComponentModel Public Class WebForm2 Inherits System.Web.UI.Page Private WithEvents BackgroundWorker1 As New System.ComponentModel.BackgroundWorker Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load BackgroundWorker1.WorkerReportsProgress = True BackgroundWorker1.WorkerSupportsCancellation = True End Sub


        Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Label3.Text = "YES"
            'ScriptManager.RegisterStartupScript(updatepanel1, Me.GetType, "setmensajeJScript_C", "recargar();", True)
            updatepanel1.Update()
            Dim logica As New logica(TextBox1.Text)
            BackgroundWorker1.RunWorkerAsync(logica)
            ' Page.ClientScript.RegisterStartupScript(Me.GetType(), "setmensajeJScript_A", "recargar();", True)
            'ScriptManager.RegisterStartupScript(updatepanel1, Me.GetType, "setmensajeJScript_C", "recargar();", True)
            Dim logica2 As New logica("PRUEBA")
            logica2.getCiclos()
        

        End Sub Protected Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Label3.Text = "YES" updatepanel1.Update() Dim Thread As New System.Threading.Thread(AddressOf TestArea1) Thread.Start() End Sub Public Delegate Sub AddLabelTextDelegate(ByVal label As Label, ByVal value As String) Public midelegado As AddLabelTextDelegate Public Sub AddLabelText(ByVal label As Label, ByVal value As String) label.Text = value Me.updatepanel1.Update() End Sub Private Sub TestArea1() Label4.Text = "ANTES DE LLAMAR AL BACKGRAUND" updatepanel1.Update() Dim logica As New logica(TextBox1.Text) BackgroundWorker1.RunWorkerAsync(logica) Label4.Text = "DESPUES DE LLAMAR AL BACKGRAUND" updatepanel1.Update() End Sub ' This method runs on the background thread when it starts. Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork BackgroundWorker1.ReportProgress(5) Dim logica As logica = CType(e.Argument, logica) ' Return the value through the Result property. e.Result = logica.getCiclos End Sub ' This method runs on the main thread when the background thread finishes. Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted ' Access the result through the Result property. Dim Area As String = CStr(e.Result) If (TextBox1.Text = "A") Then 'Label1.Text = "The area is: " & Area.ToString Me.midelegado = New AddLabelTextDelegate(AddressOf AddLabelText) midelegado.Invoke(Label1, "The area is: " & Area.ToString) 'updatepanel1.Update() 'ScriptManager.RegisterStartupScript(updatepanel1, Me.GetType(), "setmensajeJScript_A", "recargar();", True) System.Diagnostics.Debug.WriteLine(Label1.Text) ElseIf (TextBox1.Text = "B") Then Label2.Text = ": " & Area.ToString updatepanel1.Update() 'Page.ClientScript.RegisterStartupScript(Me.GetType(), "setmensajeJScript_B", "recargar();", True) System.Diagnostics.Debug.WriteLine(Label2.Text) ElseIf (TextBox1.Text = "C") Then Label3.Text = "The " & Area.ToString updatepanel1.Update() 'Page.ClientScript.RegisterStartupScript(Me.GetType(), "setmensajeJScript_C", "recargar();", True) System.Diagnostics.Debug.WriteLine(Label3.Text) End If End Sub End Class


    jueves, 2 de julio de 2015 23:15

Todas las respuestas

  • Me temo que tienes montada una confusión tremenda entre la forma en que se usan los hilos en una aplicación de escritorio y la forma en que operan las aplicaciones de tipo web.

    El Backgroundworker únicamente tiene sentido en las aplicaciones de escritorio. Ahí es donde se usa el runworkercompleted para devolver el resultado, y también es donde hay que recurrir al Invoke para actualizar la interfaz de usuario (que es monohilo) desde el hilo de background.

    Nada de todo eso tiene ningún sentido en una apicación web. En éstas, cada vez que haces "click" en un botón para llamar al servidor se crea siempre un nuevo hilo en éste para atender a esa petición. No tienes que usar un backgroundworker. Y la interfaz de usuario está en otra máquina distinta (es html en el navegador). No funciona como en una aplicación de escritorio, en la que puedes modificar un label y el label cambia en pantalla. En web, el navegador envía una petición al servidor; esto construye la clase del form (en un nuevo hilo), ejecuta el código, y el código mete valores en los controles; con esos valores de los controles se genera HTML que se devuelve a la página, y con eso el navegador presenta el resultado. A continuación la clase SE DESTRUYE. Si creas un hilo dentro de la clase, eso la mantiene viva e impide que el GC la destruya, pero si en ese momento cambias algo en un Label, ese label ya no se muestra en pantalla (porque ya se envió el HTML a la misma, ya no hay manera de cambiárselo desde el servidor).

    Así que me temo que tendrás que replantearte el diseño que tenías en mente, que está orientado a aplicaciones de escritorio pero no sirve para Webforms.

    viernes, 3 de julio de 2015 6:28