thread progressBar in WinForms

En el último post y en “WinForms”, comentamos como en algunas circunstancias se nos produce una excepción de ‘Subproceso Anulado’ cuando creamos/destruimos hilos en una misma función.


Después de conversar sobre el tema, y hablando con uno de vosotros sobre un escenario donde en ‘WinForm’ clásico nunca ha sido capaz de visualizar una ‘progress bar’ independientemente del form principal y aun pensando que deben existir montón de ejemplos J me he decidido a juguetear un ratito para ver como lo haría yo…


Este es el resultado (no sé si muy bueno, pero funciona.)


De todas maneras se me ocurre, que en próximos post podríamos hablar de cómo hacerlo usando “async”  “await” y “task”. Que os parece?


Si lo consideráis interesante no dudéis pedirme el equivalente en C#.



In the last post we are discussing around “WinForms” and some exceptions when create / destroy threads inside the same function.

After talking more about this, and share with somebody of you who are using classic ‘WinForm’ and has never been able to display a ‘progress bar’ independently of the main form, I think that we can found a plenty of examples on the web, But I decided tinkering for a while to see how I’d do it …

This is the result (not sure if is a very good sample, but it works.)

Anyway, it occurs to me that in next post could talk about how to do it using “async” “await” and “task”. What you think?

Do not hesitate to ask me for the equivalent code in C #.


Espero vuestros comentarios!



Imports System.Threading
Public Class Main
 
    Private WithEvents tmr As New System.Timers.Timer(1000)
    Private currentPrgBar As Form
    Private createPrgBar As Boolean = False
    Private disposePrgBar As Boolean = False
 
    Delegate Sub myDeleg(toClose As Form)
 
    ''' When running button is presed
    Private Sub simulateLoad(sender As Object, e As EventArgsHandles btnRunning.Click
        createPrgBar = True
        btnRunning.Text = "Load in progress"
        For index = 1 To 10000
            btnRunning.Text = "Running loop :" + index.ToString
            btnRunning.Refresh()
            Application.DoEvents()
        Next
        btnRunning.Text = "Run New loop"
        disposePrgBar = True
    End Sub
 
    ''' watch if any process are running to create a new progress bar
    Private Sub tmr_Tick(sender As Object, e As EventArgsHandles tmr.Elapsed
        If createPrgBar And (currentPrgBar Is NothingThen
            Dim myThread As New Thread(AddressOf onFlyStatusBarForm)
            myThread.Start()
            createPrgBar = False
        Else
            If disposePrgBar Then
                closeForm(currentPrgBar)
                disposePrgBar = False
            End If
        End If
    End Sub
    ''' When form load
    Private Sub Main_Load(sender As Object, e As EventArgsHandles MyBase.Load
        tmr.Interval = 100
        tmr.Start()
    End Sub
    ''' When main form closes
    Private Sub Main_FormClosing(sender As Object, e As FormClosingEventArgsHandles MyBase.FormClosing
        closeForm(currentPrgBar)
    End Sub
 
    ''' Create new 'processing' progressBar
    Sub onFlyStatusBarForm()
        Dim lblMessage As New Label With {.Dock = DockStyle.Top,
                                          .Text = "Procesing, please wait..",
                                          .TextAlign = ContentAlignment.MiddleCenter,
                                          .Font = New System.Drawing.Font("Microsoft Sans Serif"14.0!,
                                                                          System.Drawing.FontStyle.Bold,
                                                                          System.Drawing.GraphicsUnit.Point,
                                                                          CType(0Byte))
                                         }
        Dim prgBar As New ProgressBar With {.Height = 15, .Dock = DockStyle.Bottom, .Style = ProgressBarStyle.Marquee}
 
        currentPrgBar = New Form() With {.Width = 300, .Height = 50,
                               .StartPosition = FormStartPosition.CenterScreen,
                               .ControlBox = False,
                               .FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D
                              }
 
        currentPrgBar.Controls.AddRange(New Control() {lblMessage, prgBar})
        AddHandler currentPrgBar.LostFocus, AddressOf recoverFocus
        Application.Run(currentPrgBar)
    End Sub
 
    ''' Make current prgBar topmost if lost focus
    Private Sub recoverFocus(sender As Object, e As EventArgs)
        currentPrgBar.TopMost = True
    End Sub
 
    ''' Close current 'progressBar'
    Sub closeForm(toClose As Form)
        If toClose Is Nothing Then Exit Sub
        If toClose.InvokeRequired Then
            toClose.Invoke(New myDeleg(AddressOf closeForm), toClose)
        Else
            toClose.Close()
            currentPrgBar = Nothing
        End If
    End Sub
 
End Class

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>