Show and Hide a label in a panel in VB - vb.net

I was surprised to find that in VB one can not easily set the font and backcolour of a tooltip item by it's default properties so I thought I would create my own.
Private aTimer As New System.Timers.Timer
Private Sub Panel1_MouseHover(sender As Object, e As EventArgs) Handles Panel1.MouseHover
Hover("How's about that")
End Sub
Private Sub Hover(ByRef Tip As String)
If Not lblToolTip.Visible Then
lblToolTip.Text = Tip
lblToolTip.Location = Me.PointToClient(MousePosition)
lblToolTip.Visible = True
lblToolTip.BringToFront()
StartTimer()
End If
End Sub
Private Sub StartTimer()
aTimer.Interval = 2000
AddHandler aTimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf aTimer_Elapsed)
aTimer.Start()
End Sub
Sub aTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
aTimer.Stop()
lblToolTip.Visible = False
End Sub
Everything goes ok until I try to hide the label when I get the error -
'Cross - thread operation Not valid: Control 'lblToolTip' accessed from a thread other than the thread it was created on.'
I have researched the error for a couple of days but I am afraid it is a bit too deep a thread for an 80 old year after a stroke. I would appreciate any pointers to direct me to the solution.

You could have used a Forms Timer and not had this problem.
Since you didn't, replace your aTimer_Elapsed method with this.
Sub aTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
aTimer.Stop()
Me.BeginInvoke(Sub()
lblToolTip.Visible = False
End Sub)
End Sub

Try use Delegate
Private aTimer As New System.Timers.Timer
Private Delegate Sub SafeCallDelegate(ByVal label As Label, ByVal Visible As Boolean, ByVal Text As String)
Private Sub Panel1_MouseHover(sender As Object, e As EventArgs) Handles Panel1.MouseHover
Hover("How's about that")
End Sub
Private Sub StartTimer()
aTimer.Interval = 2000
AddHandler aTimer.Elapsed, New System.Timers.ElapsedEventHandler(AddressOf aTimer_Elapsed)
aTimer.Start()
End Sub
Sub aTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
aTimer.Stop()
SetLabelProperty(lblToolTip, False)
End Sub
Private Sub SetLabelProperty(ByVal label As Label, ByVal Visible As Boolean, Optional ByVal Text As String = "")
If label.InvokeRequired Then
label.Invoke(New SafeCallDelegate(AddressOf SetLabelProperty), New Object() {label, Visible, Text})
Else
label.Visible = Visible
label.Location = Me.PointToClient(MousePosition)
label.Text = Text
lblToolTip.BringToFront()
End If
End Sub
Private Sub Hover(ByRef Tip As String)
If Not lblToolTip.Visible Then
SetLabelProperty(lblToolTip, True, Tip)
StartTimer()
End If
End Sub
Look this example:
Update Text Box Properly when Cross-threading in Visual Basic (VS 2012 V11)

This was the result
Public Sub ToolTip_Draw(sender As Object, e As DrawToolTipEventArgs)
e.DrawBackground()
e.DrawBorder()
e.Graphics.DrawString(e.ToolTipText, New Font("Arial", 10), System.Drawing.Brushes.Black, New PointF(2, 2))
End Sub
Public Sub ToolTip_Popup(sender As Object, e As PopupEventArgs)
Dim Sz As Size = TextRenderer.MeasureText(sender.GetToolTip(e.AssociatedControl), New Font("Arial", 10))
e.ToolTipSize = New Size(Sz.Width, Sz.Height + 4)
End Sub
The backcolour is set in the properties. The size is determined by the PipUp.

Related

VB.Net Send output and input of process started in another form

I have 2 forms, MainForm and RCONForm.
What I am trying to do is to start a process when the programs starts and in this case I have choosen cmd.exe and it works.
The thing is I want to be able to read the output and send input onto the process from another form using 2 textboxes.
The problem is that I can't read anything from the process neither can I send any input to it either.
My MainForm:
Public Class MainForm
#Region "Import Function"
Dim Functions As New Functions
Friend WithEvents RCON As Process
#End Region
Friend Sub AppendOutputText(ByVal text As String)
If RCONForm.RCONLogText.InvokeRequired Then
Dim myDelegate As New RCONForm.AppendOutputTextDelegate(AddressOf AppendOutputText)
Me.Invoke(myDelegate, text)
Else
RCONForm.RCONLogText.AppendText(text)
End If
End Sub
Private Sub MainForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
RCON = New Process
With RCON.StartInfo
.FileName = "C:\Windows\system32\CMD.exe"
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardInput = True
.RedirectStandardOutput = True
.RedirectStandardError = True
End With
RCON.Start()
RCON.BeginErrorReadLine()
RCON.BeginOutputReadLine()
AppendOutputText("RCON Started at: " & RCON.StartTime.ToString)
End Sub
Private Sub RCONButton_Click(sender As Object, e As EventArgs) Handles RCONButton.Click
Functions.KillOldForm()
Functions.SpawnForm(Of RCONForm)()
End Sub
Private Sub ExitButton_Click(sender As Object, e As EventArgs) Handles ExitButton.Click
Application.Exit()
End Sub
Private Sub ServerButton_Click(sender As Object, e As EventArgs) Handles ServerButton.Click
Functions.KillOldForm()
Functions.SpawnForm(Of ServerForm)()
End Sub
End Class
And my RCONForm:
Public Class RCONForm
Friend Delegate Sub AppendOutputTextDelegate(ByVal text As String)
Friend WithEvents RCON As Process = MainForm.RCON
Friend Sub RCON_ErrorDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles RCON.ErrorDataReceived
MainForm.AppendOutputText(vbCrLf & "Error: " & e.Data)
End Sub
Friend Sub RCON_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles RCON.OutputDataReceived
MainForm.AppendOutputText(vbCrLf & e.Data)
End Sub
Friend Sub RCONCommandText_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles RCONCommandText.KeyPress
If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then
MainForm.RCON.StandardInput.WriteLine(RCONCommandText.Text)
MainForm.RCON.StandardInput.Flush()
RCONCommandText.Text = ""
e.Handled = True
End If
End Sub
Friend Sub RCONForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
MainForm.RCON.StandardInput.WriteLine("EXIT") 'send an EXIT command to the Command Prompt
MainForm.RCON.StandardInput.Flush()
MainForm.RCON.Close()
End Sub
Private Sub RCONForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
End Class
My Functions:
#Region "Kill Old Forms"
Function KillOldForm()
While MainForm.SpawnPanel.Controls.Count > 0
MainForm.SpawnPanel.Controls(0).Dispose()
End While
Return Nothing
End Function
#End Region
#Region "Spawn Form"
Function SpawnForm(Of T As {New, Form})() As T
Dim spawn As New T() With {.TopLevel = False, .AutoSize = False}
Try
spawn.Dock = DockStyle.Fill
MainForm.SpawnPanel.Controls.Add(spawn)
spawn.Show()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return Nothing
End Function
#End Region
I have been thinking of using threads and maybe that can solve the issue, or is there a more simple way?
You are using default form instances heavily. You should avoid that if possible. Here's a way to keep track of the proper instance of RCONForm in MainForm
Private myRCONForm As RCONForm
Private Sub RCONButton_Click(sender As Object, e As EventArgs) Handles RCONButton.Click
Functions.KillOldForm()
myRCONForm = Functions.SpawnForm(Of RCONForm)()
End Sub
Now SpawnForm is a function, and it would return the form so you can keep a reference to it
Public Function SpawnForm(Of T As {New, Form})() As T
Dim myForm = New T()
' add myForm to the appropriate Panel or whatever
Return myForm
End Function
Update all access to RCONForm with myRCONForm in MainForm
Also, this is a little flawed, where you check if invocation is required on RCONForm.RCONLogText, then invoke on Me. It can be simplified
' old with default form instance
Friend Sub AppendOutputText(ByVal text As String)
If RCONForm.RCONLogText.InvokeRequired Then
Dim myDelegate As New RCONForm.AppendOutputTextDelegate(AddressOf AppendOutputText)
Me.Invoke(myDelegate, text)
Else
RCONForm.RCONLogText.AppendText(text)
End If
End Sub
' new, with instance reference plus simplified invocation
Friend Sub AppendOutputText(text As String)
If myRCONForm.RCONLogText.InvokeRequired Then
myRCONForm.RCONLogText.Invoke(New Action(Of String)(AddressOf AppendOutputText), text)
Else
myRCONForm.RCONLogText.AppendText(text)
End If
End Sub

Adding 150,000 records to a listview without freezing UI

I have a listview loop that is adding 150,000 items to my listview. For testing purposes I moved this code to a background worker with delegates, but it still freezes up the UI. I am trying to find a solution so that it can add these items in the background while I do other stuff in the app. What solutions do you guys recommend?
this is what I am using
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ListView1.Clear()
ListView1.BeginUpdate()
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If bw.IsBusy Then bw.CancelAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
For x = 1 To 125000
Dim lvi As New ListViewItem("Item " & x)
If bw.CancellationPending Then
e.Cancel = True
Exit For
Else
bw.ReportProgress(0, lvi)
End If
Next
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
Try
Dim lvi As ListViewItem = DirectCast(e.UserState, ListViewItem)
Me.ListView1.Items.Add(lvi)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
ListView1.EndUpdate()
If Not e.Cancelled Then
Debug.Print("Done")
Else
Debug.Print("Cancelled")
End If
End Sub
End Class
Give this a try, it's a great example for what you would need... I also had a progress bar that shows the progress and such, see example image that is attached. Also I wasn't seeing any delegate that you need to perform such operation, mine has one that will be required. The reason is you are adding items to a control on the UI thread, in order to add items we need to know if an Invoke is required, if so we invoke otherwise we add the item to the control... Also I made the thread sleep, so it can take a break; this also prevents the UI from wanting to lock up here and there, now it's responsive with NO FREEZING.
Option Strict On
Option Explicit On
Public Class Form1
Delegate Sub SetListItem(ByVal lstItem As ListViewItem) 'Your delegate..
'Start the process...
Private Sub btnStartProcess_Click(sender As Object, e As EventArgs) Handles btnStartProcess.Click
lvItems.Clear()
bwList.RunWorkerAsync()
End Sub
Private Sub AddListItem(ByVal lstItem As ListViewItem)
If Me.lvItems.InvokeRequired Then 'Invoke if required...
Dim d As New SetListItem(AddressOf AddListItem) 'Your delegate...
Me.Invoke(d, New Object() {lstItem})
Else 'Otherwise, no invoke required...
Me.lvItems.Items.Add(lstItem)
End If
End Sub
Private Sub bwList_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwList.DoWork
Dim intCount As Integer = CInt(txtCount.Text)
Dim dblPercent As Integer = 100
Dim intComplete As Integer = 0
Dim li As ListViewItem = Nothing
For i As Integer = 1 To CInt(txtCount.Text)
If Not (bwList.CancellationPending) Then
li = New ListViewItem
li.Text = "Item " & i.ToString
AddListItem(li)
Threading.Thread.Sleep(1) 'Give the thread a very..very short break...
ElseIf (bwList.CancellationPending) Then
e.Cancel = True
Exit For
End If
intComplete = CInt(CSng(i) / CSng(intCount) * 100)
If intComplete < dblPercent Then
bwList.ReportProgress(intComplete)
End If
If li IsNot Nothing Then
li = Nothing
End If
Next
End Sub
Private Sub bwList_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bwList.ProgressChanged
pbList.Value = e.ProgressPercentage
End Sub
Private Sub bwList_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwList.RunWorkerCompleted
If pbList.Value < 100 Then pbList.Value = 100
MessageBox.Show(lvItems.Items.Count.ToString & " items were added!")
End Sub
Private Sub btnStopWork_Click(sender As Object, e As EventArgs) Handles btnStopWork.Click
bwList.CancelAsync()
End Sub
Private Sub btnRestart_Click(sender As Object, e As EventArgs) Handles btnRestart.Click
pbList.Value = 0
lvItems.Items.Clear()
txtCount.Text = String.Empty
End Sub
End Class
Screenshot in action...

Multithreading for a progressbar and code locations (vb.net)?

I am stuck updating a progressbar from a different thread.
I did get it running in the simplest way, but then cleaning the code gets me stuck.
My testing code looks like all the examples on the web related to backgroundworker and BeginInvoke.
FormP is the Progressbar-Form.
This works:
Public Class Form1
Private Delegate Sub delegate_ProgressUpdate(ByVal paramValue As Integer,
ByVal paramMax As Integer)
Private Sub Button1_Click(sender As System.Object,
e As System.EventArgs) Handles Button1.Click
' Test 01:
' Show Progressbar via BGW
' All functions are within Form1
Dim bgw As New BackgroundWorker()
AddHandler bgw.DoWork, AddressOf BGW_Sample01_DoWork
FormP.Show(Me)
bgw.RunWorkerAsync()
End Sub
Private Sub invokeMe_ProgressUpdate(ByVal paramValue As Integer, ByVal paramMax As Integer)
FormP.ProgressBar1.Maximum = paramMax
FormP.ProgressBar1.Value = paramValue
FormP.ProgressBar1.Update()
End Sub
Private Sub BGW_Sample01_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
For i As Integer = 1 To 10
Threading.Thread.Sleep(500) ' Test delay
Me.BeginInvoke(New delegate_ProgressUpdate(AddressOf invokeMe_ProgressUpdate),
i, 10)
Next
MessageBox.Show("Fertig")
End Sub
If I try to make things work more orderly encapsulated in FormP, it doesn't work.
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim bgw As New BackgroundWorker
AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
FormP.Show(Me)
bgw.RunWorkerAsync()
End Sub
Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
For i As Integer = 1 To 10
Threading.Thread.Sleep(500)
FormP.SetProgress(i, 10)
Next
MessageBox.Show("Fertig")
End Sub
' ########## FormP #################
Public Class FormP
Private Delegate Sub delegate_ProgressUpdate(ByVal value As Integer, ByVal maximum As Integer)
Public Sub SetProgress(ByVal paramValue As Integer, ByVal paramMaximum As Integer)
If Me.InvokeRequired Then
Me.Invoke(New delegate_ProgressUpdate(AddressOf Me.SetProgress), paramValue, paramMaximum)
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
Me.ProgressBar1.Update()
End If
End Sub
End Class
FormP does not freeze, but UI is not updated.
Actually Me.InvokeRequired is false and I think that's where I begin to miss some important parts.
I tried Form1.InvokeRequired here, but it's false as well.
My understanding is: the calling thread here is the bgw thread, no matter in what class the code is that this thread calls...
That seems not to be it?
Thanks for any thoughts.
What worked eventually:
Private frmP As FormP
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim bgw As New BackgroundWorker
If Me.frmP IsNot Nothing AndAlso Me.frmP.Visible Then Return
Me.frmP = New FormP
Me.frmP.Show(Me)
AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
bgw.RunWorkerAsync(New Object() {Me.frmP})
End Sub
Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
Dim objFrmP As FormP = DirectCast(e.Argument(0), FormP)
For i As Integer = 1 To 10
objFrmP.setProgress(i, 10)
Threading.Thread.Sleep(500)
Next
MessageBox.Show("Finished")
End Sub
The Progress-Dialog-Code in FormP:
Public Sub setProgress(paramValue As Integer, paramMaximum As Integer)
If Me.InvokeRequired Then
' defining a delegate type is not really necessary
Me.Invoke(Sub() Me.setProgress(paramValue, paramMaximum))
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
Me.ProgressBar1.Update()
End If
End Sub

Iteration Not Working As Intended

I'm using a DO interation to loop a function I'm using to test for internet connectivity. The code is working fine, except that when one of the tests is satisfied the loop stops. I want this to continue in the background while the program is running. How can I get this to work?
Private Sub checkInternet()
Dim InetChecker As Boolean
InetChecker = CheckForInternetConnection()
Do While LabelCount.Text <> ""
Thread.Sleep(10)
If InetChecker = True Then
Dim image = My.Resources.greenbar
PictureBox4.Image = image
Else
Thread.Sleep(10)
Dim image = My.Resources.redbar
PictureBox4.Image = image
'NoInetConnError.Show()
End If
Loop
End Sub
Your assistance would be greatly appreciated, thanks.
Put a BackgroundWorker on your form (you will find it in the Components section of the Toolbox).
In the Properties window set WorkerReportsProgress to True for your BackgroundWorker.
Insert the following code to your form
Private connected As Boolean
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
While True
Dim online = CheckForInternetConnection()
If online <> connected Then
connected = online
BackgroundWorker1.ReportProgress(CInt(online))
End If
Thread.Sleep(500)
End While
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
Handles BackgroundWorker1.ProgressChanged
Dim online As Boolean = CBool(e.ProgressPercentage)
If online Then
PictureBox4.Image = My.Resources.greenbar
Else
PictureBox4.Image = My.Resources.redbar
End If
End Sub
Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
' Start the background worker
BackgroundWorker1.RunWorkerAsync()
End Sub
Note that Sub BackgroundWorker1_DoWork runs on a separate thread and does not freeze your form while it is running.
It would be best to do something like this in a Timer and not in a loop.
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
If CheckForInternetConnection Then
PictureBox4.Image = My.Resources.greenbar
Else
PictureBox4.Image = My.Resources.redbar
End If
End Sub
If you have access to .Net framework 3+ then you could use the DispatcherTimer class which essentially creates an interval (set at whatever length you require) which you can handle the tick event for. When the tick event is raised, you can do your internet connection check.
Modifying the MSDN example for your situation, you could do something like this:
' DispatcherTimer setup
dispatcherTimer = New Threading.DispatcherTimer()
AddHandler dispatcherTimer.Tick, AddressOf dispatcherTimer_Tick
dispatcherTimer.Interval = New TimeSpan(0,0,1) ' Or however long you want
dispatcherTimer.Start()
Private Sub dispatcherTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
' Checks to see whether an internet connection is still available etc
checkInternet()
' Forcing the CommandManager to raise the RequerySuggested event
CommandManager.InvalidateRequerySuggested()
End Sub

ProgressBar Woes. Getting UI thread to update while reading database

I'm having trouble getting a progress bar to update. I'd be okay just with a moving marquee bar. Basically, I'm reading a database routine in a SqliteReader.vb class. I'm new to visual basic, and I'm sure I need to use the worker_DoWork routine, but I'm not sure how to expose my variables coming from Form1: graphData, graphComputations, m_debug to the worker_DoWork sub. How is this usually done?
Public Class SqliteReader
Public Sub ReadDataBase
End Sub
End Class
This is updating a graph (zedgraph element) on the main form, Form1.vb. I call the progressbar from the main form like this:
ProgressBar.Initialize(channelArray, computationArray, m_debug)
ProgressBar.vb below:
Partial Public Class ProgressBar
Dim DataAcquisition As New SqliteReader
Dim WithEvents worker As New BackgroundWorker
Public Sub Initialize(ByRef graphData As Channels(), ByRef graphComputations As Computations(), ByVal m_debug As Integer)
DataAcquisition = SqliteReader.GetInstance()
Me.Show()
Me.Update()
Dim Update_Thread As Thread(AddressOf Update_ThreadExecute)
Update_Thread.Priority = ThreadPriority.Normal
Update_Thread.Start()
DataAcquisition.ParseEntireDatabase(graphData, graphComputations, m_debug)
Me.Close()
End Sub
Private Sub ProgressBarStart(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataAcquisition = SqliteReader.GetInstance()
progress.Style = ProgressBarStyle.Marquee
worker.WorkerReportsProgress = True
worker.WorkerSupportsCancellation = True
worker.RunWorkerAsync()
End Sub
Private Sub worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork
Dim worker As BackgroundWorker = DirectCast(sender, BackgroundWorker)
DataAcquisition = SqliteReader.GetInstance()
' I probably need
' DataAcquisition.ParseEntireDatabase(graphData, graphComputations, m_debug)
' here... but how do I expose graphdata, graphcomputations and m_debug to this sub?
End Sub
Private Sub worker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles worker.ProgressChanged
dataProgress = CInt(((DataAcquisition.currentRow + 1) / DataAcquisition.totalRows) * 100)
progress.Value = dataProgress
End Sub
RunWorkerAsync has a second version that takes a parameter. You can use that to pass any values (or references) your worker needs.
That said, you shouldn't be updating form elements from inside the worker. Your worker should fire the ProgressChanged event when you want the UI to update, and you handle it there. That one also has a version that can send a value back. (Or many values if you send back an array, list, or custom class.)
The last step in this is that you need to actually fire ProgressChanged. DataAcquisition.ParseEntireDatabase may not do that, in which case using it won't allow this method to work.
If graphData, graphComputations, m_debug are already members of ProgressBar and worker_DoWork is a member of ProgressBar, then you have nothing more to do. You should be able to access them directly.
For Rapunzo, above.. My Final Solution was this:
Partial Public Class ProgressBar
Dim _mDataAcquisition As New SqliteReader
Public Property DataProgress As Integer = 0
Dim WithEvents _mProgressWorker As New BackgroundWorker
Public Sub Initialize(ByRef graphData As List(Of Channels), ByRef auxData As List(Of Channels), _
ByRef graphComputations As List(Of Computations))
_mDataAcquisition = SqliteReader.GetInstance()
Show()
Update()
_mDataAcquisition.ParseEntireDatabase(graphData, auxData, graphComputations)
Close()
End Sub
Private Sub ProgressBarStart(ByVal sender As System.Object, ByVal e As EventArgs) Handles MyBase.Load
progress.Style = ProgressBarStyle.Blocks
_mProgressWorker.WorkerReportsProgress = True
_mProgressWorker.WorkerSupportsCancellation = True
_mProgressWorker.RunWorkerAsync()
progress.Visible = True
progress.Maximum = 100
progress.Value = 0
End Sub
Public Sub WorkerProgressChanged()
progress.Value = DataProgress
Invalidate()
End Sub
Private Sub WorkerRunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles _mProgressWorker.RunWorkerCompleted
progress.Visible = False
progress.Value = 0
Close()
End Sub
From there, just call ProgressBar.Initialize to start it
To update:
ProgressBar.DataProgress = CInt((currentIt / totalIt) * 100)
ProgressBar.WorkerProgressChanged()
and to end:
ProgressBar.DataProgress = 100
ProgressBar.WorkerProgressChanged()
Hope this helps.