tentavarious
asked on
How to correctly use a progress bar while a long task is running visual studio 2008
Hello experts I have a task that runs when my programs main form loads. The task queries our database and dynamically creates panels and adds them to a number of flowlayoutpanel controls. This process can take some time so I want a progress bar to show up while the records are being loaded. I can't quite get the progress bar to function, its like nothing will work until the main task is complete. I am new to visual studio 2008, so am I doing something wrong. In 2003, I could use a timer or a system.thread.timer. Any ideas?
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
tloading.Start() 'Timer that controls the progress bar
record_loading_status = True
Application.DoEvents()
build_query() 'This is the main task didnt think i would need to show this procedure
tloading.Stop()
record_loading_status = False
Me.ss_status_text.Text = "Ready!"
ss_progress_bar.Visible = False
End Sub
Private Sub tloading_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tloading.Tick
If record_loading_status Then
If Me.ss_progress_bar.Value < ss_progress_bar.Maximum Then
ss_progress_bar.Increment(10)
Else
ss_progress_bar.Value = 0
End If
End If
End Sub
ASKER
Yep, I tried that, but I get this error: Cross-Thread operation not valid: Control 'flptube' accessed from a thread other then the thread it was created on. The build_query, which is the main procedure, dynamically builds panels and adds them to that control flptube.
I found something that is suppose to make the threading function more like .net 1.1
Me.CheckForIllegalCrossThr eadCalls = False. This allows the cross threading, but then I get another error. So I am kinda at a loss.
I found something that is suppose to make the threading function more like .net 1.1
Me.CheckForIllegalCrossThr
With VB.Net 2008 you set the ProgressBar.Style to Marquee and it will continuosly move to show an operation is in progress:
ss_progress_bar.Style = ProgressBarStyle.Marquee
Play with this simple example:
ss_progress_bar.Style = ProgressBarStyle.Marquee
Play with this simple example:
Public Class Form1
Private WithEvents bgw As New System.ComponentModel.BackgroundWorker
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ProgressBar1.Style = ProgressBarStyle.Marquee
bgw.WorkerReportsProgress = True
bgw.RunWorkerAsync()
End Sub
Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
' this is running in a DIFFERENT thread
For i As Integer = 1 To 5
Dim btn As New Button
btn.Location = New Point(10, i * 25)
btn.Text = "#" & i
AddHandler btn.Click, AddressOf btn_Click
bgw.ReportProgress(0, btn)
System.Threading.Thread.Sleep(2000) ' simulated "work" so you can see the progressbar "marquee" mode in action
Next
End Sub
Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
' this is running in the main UI Thread
Me.Controls.Add(e.UserState)
End Sub
Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
' this is running in the main UI Thread
ProgressBar1.Style = ProgressBarStyle.Blocks
ProgressBar1.Visible = False
End Sub
Private Sub btn_Click(ByVal sender As Object, ByVal e As System.EventArgs)
MessageBox.Show(sender.text)
End Sub
End Class
That CheckForIllegalCrossThread Calls property in .NET 1.1 was a bit of a cheat. In .NET 2.0 and up you need to check to see if an invoke is required and if so marshall the call back to the UI thread. I've attached some code that does this.
In this case the method that I'm calling (BuildDeployList) doesn't take any argument so I can use the Action delegate that is built into the framework. If your method (the one that adds the panel to the UI) takes argument you'll need to declare a delegate for it and use it in place of Action, or use the generic Action delegate. For example:
private delegate void SetToolStripItemEnabledSta teDelegate ( ToolStripItem item, bool state );
or
Action<int, string>
In this case the method that I'm calling (BuildDeployList) doesn't take any argument so I can use the Action delegate that is built into the framework. If your method (the one that adds the panel to the UI) takes argument you'll need to declare a delegate for it and use it in place of Action, or use the generic Action delegate. For example:
private delegate void SetToolStripItemEnabledSta
or
Action<int, string>
private void BuildDeployList()
{
if( this.InvokeRequired )
{
Action action = BuildDeployList;
this.Invoke( action );
}
else
{
AddTestsToListBox( lstAvailableTests, Directory.GetFiles( DeployFolder, "*.zip" ) );
SetControlStates();
}
}
ASKER
Ok, I am a little confused on how to get this to work
Here is the thread that executes the query: build_query, and updates the progress bar. Within the the build_query I call another procedure that interacts with the control and gets passed 8 paramaters. I am unsure how to make this work.
I took out a lot of code that involves query the db and adding some stuff that doesnt matter with my question. If you look at the build_panel procedure the last line where I try to add the controls is where the error occurs. I am not sure how to declare the delegate.
Here is the thread that executes the query: build_query, and updates the progress bar. Within the the build_query I call another procedure that interacts with the control and gets passed 8 paramaters. I am unsure how to make this work.
I took out a lot of code that involves query the db and adding some stuff that doesnt matter with my question. If you look at the build_panel procedure the last line where I try to add the controls is where the error occurs. I am not sure how to declare the delegate.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim worker As New System.Threading.Thread(AddressOf build_query)
worker.Start()
While worker.IsAlive
Threading.Thread.Sleep(900)
If Me.ss_progress_bar.Value < ss_progress_bar.Maximum Then
ss_progress_bar.Increment(10)
Else
ss_progress_bar.Value = 0
End If
End While
ss_progress_bar.Value = ss_progress_bar.Minimum
End Sub
Sub build_query()
Dim data_adap As OracleDataAdapter
Dim ds As New DataSet
Dim dr As DataRow
Dim job, item, description, qty, temp_qty As String
Dim col_name As String
Dim sched_start_date As Date
ssql = "select columns here from table name"
data_adap = New OracleDataAdapter(ssql, ora_conn)
Try
data_adap.Fill(ds, "Table1")
For Each dr In ds.Tables(0).Rows
job = dr.Item(0).ToString
item = dr.Item(1).ToString
description = dr.Item(2).ToString
sched_start_date = dr.Item(3)
qty = dr.Item(4).ToString
For i As Integer = 5 To ds.Tables(0).Columns.Count - 1
Dim l As New Label
Dim v As Array
col_name = ds.Tables(0).Columns.Item(i).ColumnName
v = Me.Controls.Find("flp" & col_name.ToLower, True)
If v.Length >= 1 Then
temp_qty = dr.Item(i + 1).ToString
build_panel(job, item, description, sched_start_date, qty, temp_qty, v(0), dr.Item(i).ToString)
i += 1
End If
Next
row_count += 1
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Sub build_panel(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Dim ptemp As New Panel
Dim l_desc As New Label
Dim l_part_num As New Label
Dim l_qty As New Label
Dim l_date As New Label
With l_part_num
.Text = part_number
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 8)
.Location = New Point(ptemp.Location.X + 22, ptemp.Location.Y - 1)
End With
With l_desc
.Text = description
.ForeColor = Color.Black
.Font = New Font(Font.Name, 5.5, FontStyle.Regular)
.AutoSize = True
.Location = New Point(ptemp.Location.X + 1, ptemp.Location.Y + 13)
End With
With l_date
.Text = shed_date.ToString("M/d")
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 7)
.Location = New Point(ptemp.Location.X - 2, ptemp.Location.Y - 1)
End With
With l_qty
.Text = run_qty & "/" & total_qty
.ForeColor = Color.Black()
.BackColor = Color.White
.AutoSize = True
.RightToLeft = Windows.Forms.RightToLeft.Inherit
.Location = New Point(ptemp.Location.X + 27, ptemp.Location.Y + 21)
.Font = New Font(Font.Name, 7)
.TextAlign = ContentAlignment.MiddleCenter
End With
ptemp.Controls.Add(l_part_num)
ptemp.Controls.Add(l_date)
ptemp.Controls.Add(l_desc)
ptemp.Controls.Add(l_qty)
temp_panel.Controls.Add(ptemp)
End Sub
Because it takes eight parameters you won't be able to use Action, it maxes out at four parameters.
I don't use VB.NET, I'm developing in C#, so I don't know the syntax for declaring a delegate off the top of my head in VB.NET.
Accoding to this page (http://www.developerfusion.com/article/5251/delegates-in-vbnet) the declaration is the same as any other variable in VB.NET.
Private Delegate Sub MyDelSub()
The delegate is a variable that represents your method, so it must match the method in terms of arguments and return type. In your case:
Private Delegate Sub BuildPanelDelegate(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Create an if/else statement with a condition checking the form for InvokeRequired. Put all the existing code in the else block. In the if block, declare an instance of the delegate and invoke it.
Some of the syntax may be wrong, as I mentioned I don't use VB.NET and I'm hand-coding this without benefit of Intellisense.
I don't use VB.NET, I'm developing in C#, so I don't know the syntax for declaring a delegate off the top of my head in VB.NET.
Accoding to this page (http://www.developerfusion.com/article/5251/delegates-in-vbnet) the declaration is the same as any other variable in VB.NET.
Private Delegate Sub MyDelSub()
The delegate is a variable that represents your method, so it must match the method in terms of arguments and return type. In your case:
Private Delegate Sub BuildPanelDelegate(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Create an if/else statement with a condition checking the form for InvokeRequired. Put all the existing code in the else block. In the if block, declare an instance of the delegate and invoke it.
Some of the syntax may be wrong, as I mentioned I don't use VB.NET and I'm hand-coding this without benefit of Intellisense.
If Me.InvokeRequired Then
' Declare a variable to hold a pointer to the function
Dim theDelegate As BuildPanelDelegate
' Assign the variable the address of the function to call
theDelegate = new BuildPanelDelegate(AddressOf build_panel)
' Marshall the function call back to the UI thread
theDelegate.Invoke( job_number, item_number, etc... the rest of the arguments)
Else
' all the existing code goes here
End If
ASKER
I set up the delegate and it loads the procedure fine, but I still get the same error when it tries to add controls to the panel. Not sure what i am doing wrong.
Public Delegate Sub delegate_panel(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number)
Else
'other work here
end if
Sub delegate_panel_build(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Dim ptemp As New Panel
Dim l_desc As New Label
Dim l_part_num As New Label
Dim l_qty As New Label
Dim l_date As New Label
With l_part_num
.Text = part_number
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 8)
.Location = New Point(ptemp.Location.X + 22, ptemp.Location.Y - 1)
End With
With l_desc
.Text = description
.ForeColor = Color.Black
.Font = New Font(Font.Name, 5.5, FontStyle.Regular)
.AutoSize = True
.Location = New Point(ptemp.Location.X + 1, ptemp.Location.Y + 13)
End With
With l_date
.Text = shed_date.ToString("M/d")
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 7)
.Location = New Point(ptemp.Location.X - 2, ptemp.Location.Y - 1)
End With
If run_qty = "" Then run_qty = 123
With l_qty
.Text = run_qty & "/" & total_qty
.ForeColor = Color.Black()
.BackColor = Color.White
.AutoSize = True
.RightToLeft = Windows.Forms.RightToLeft.Inherit
.Location = New Point(ptemp.Location.X + 27, ptemp.Location.Y + 21)
.Font = New Font(Font.Name, 7)
.TextAlign = ContentAlignment.MiddleCenter
End With
If part_number <> "" Then
ptemp.Controls.Add(l_part_num)
ptemp.Controls.Add(l_date)
ptemp.Controls.Add(l_desc)
ptemp.Controls.Add(l_qty)
ptemp.Tag = job_number & "~" & item_number & "~" & part_number
ptemp.Width = temp_panel.Width - 5
ptemp.Height = 34
ptemp.BorderStyle = BorderStyle.None
ptemp.BackColor = Color.Yellow
AddHandler ptemp.Click, AddressOf Ptemp_Click
AddHandler l_desc.Click, AddressOf Ptemp_Click
AddHandler l_qty.Click, AddressOf Ptemp_Click
AddHandler l_part_num.Click, AddressOf Ptemp_Click
AddHandler l_date.Click, AddressOf Ptemp_Click
Else
ptemp.Tag = "0"
ptemp.Width = temp_panel.Width
ptemp.Height = 34
ptemp.BorderStyle = BorderStyle.None
ptemp.BackColor = Color.Transparent
End If
temp_panel.Controls.Add(ptemp)
End Sub
A delegate is a variable declaration, not a method declaration. It looks like you declared your delegate and then gave a method body to it. If what you pasted is your actual code, I'm a little surprised it even compiled, but as I've said before, I don't use VB.NET.
See below for how it should be set up.
See below for how it should be set up.
Private Delegate Sub delegate_panel(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Sub delegate_panel_build(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number)
Else
Dim ptemp As New Panel
Dim l_desc As New Label
Dim l_part_num As New Label
Dim l_qty As New Label
Dim l_date As New Label
With l_part_num
.Text = part_number
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 8)
.Location = New Point(ptemp.Location.X + 22, ptemp.Location.Y - 1)
End With
With l_desc
.Text = description
.ForeColor = Color.Black
.Font = New Font(Font.Name, 5.5, FontStyle.Regular)
.AutoSize = True
.Location = New Point(ptemp.Location.X + 1, ptemp.Location.Y + 13)
End With
With l_date
.Text = shed_date.ToString("M/d")
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 7)
.Location = New Point(ptemp.Location.X - 2, ptemp.Location.Y - 1)
End With
If run_qty = "" Then run_qty = 123
With l_qty
.Text = run_qty & "/" & total_qty
.ForeColor = Color.Black()
.BackColor = Color.White
.AutoSize = True
.RightToLeft = Windows.Forms.RightToLeft.Inherit
.Location = New Point(ptemp.Location.X + 27, ptemp.Location.Y + 21)
.Font = New Font(Font.Name, 7)
.TextAlign = ContentAlignment.MiddleCenter
End With
If part_number <> "" Then
ptemp.Controls.Add(l_part_num)
ptemp.Controls.Add(l_date)
ptemp.Controls.Add(l_desc)
ptemp.Controls.Add(l_qty)
ptemp.Tag = job_number & "~" & item_number & "~" & part_number
ptemp.Width = temp_panel.Width - 5
ptemp.Height = 34
ptemp.BorderStyle = BorderStyle.None
ptemp.BackColor = Color.Yellow
AddHandler ptemp.Click, AddressOf Ptemp_Click
AddHandler l_desc.Click, AddressOf Ptemp_Click
AddHandler l_qty.Click, AddressOf Ptemp_Click
AddHandler l_part_num.Click, AddressOf Ptemp_Click
AddHandler l_date.Click, AddressOf Ptemp_Click
Else
ptemp.Tag = "0"
ptemp.Width = temp_panel.Width
ptemp.Height = 34
ptemp.BorderStyle = BorderStyle.None
ptemp.BackColor = Color.Transparent
End If
temp_panel.Controls.Add(ptemp)
End If
End Sub
ASKER
Ok, I changed it to what you had, now it gets into a never ending loop when it checks the condition
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number)
else
end if
Something is not right I dont think i am calling the procedure right. When the form loads it create the worker thread which calls the build_query procedure. Within the build_query procedure, I loop the contents of a dataset, then call the delegate_panel_build procedure which contains the delegate call and invoke. Is this right so far, if it is something is wrong.
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number,
else
end if
Something is not right I dont think i am calling the procedure right. When the form loads it create the worker thread which calls the build_query procedure. Within the build_query procedure, I loop the contents of a dataset, then call the delegate_panel_build procedure which contains the delegate call and invoke. Is this right so far, if it is something is wrong.
Private Delegate Sub delegate_panel(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim worker As New System.Threading.Thread(AddressOf build_query)
worker.Start()
While worker.IsAlive
Threading.Thread.Sleep(700)
If Me.ss_progress_bar.Value < ss_progress_bar.Maximum Then
ss_progress_bar.Increment(10)
Else
ss_progress_bar.Value = 0
End If
End While
ss_progress_bar.Value = ss_progress_bar.Minimum
End Sub
Sub build_query()
Dim data_adap As OracleDataAdapter
Dim ds As New DataSet
Dim row_count As Integer = 0 'keeps track of the rows
Dim dr As DataRow
Dim job, item, description, qty, temp_qty As String
Dim col_name As String
Dim sched_start_date As Date
ssql = "select here"
data_adap = New OracleDataAdapter(ssql, ora_conn)
Try
data_adap.Fill(ds, "Table1")
For Each dr In ds.Tables(0).Rows
job = dr.Item(0).ToString
item = dr.Item(1).ToString
description = dr.Item(2).ToString
sched_start_date = dr.Item(3)
qty = dr.Item(4).ToString
For i As Integer = 5 To ds.Tables(0).Columns.Count - 1
'This loop is for looping all the cylinder components
Dim l As New Label
Dim v As Array
col_name = ds.Tables(0).Columns.Item(i).ColumnName 'Get the column name so they can be sorted by component
v = Me.Controls.Find("flp" & col_name.ToLower, True)
If v.Length >= 1 Then
temp_qty = dr.Item(i + 1).ToString
delegate_panel_buildjob, item, description, sched_start_date, qty, temp_qty, v(0), dr.Item(i).ToString)
i += 1
End If
Next
row_count += 1
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
End Try
End Sub
Sub delegate_panel_build(ByVal job_number As String, ByVal item_number As String, ByVal description As String, ByVal shed_date As Date, ByVal total_qty As String, ByVal run_qty As String, ByVal temp_panel As FlowLayoutPanel, ByVal part_number As String)
Dim ptemp As New Panel
Dim l_desc As New Label
Dim l_part_num As New Label
Dim l_qty As New Label
Dim l_date As New Label
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number)
Else
With l_part_num
.Text = part_number
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 8)
.Location = New Point(ptemp.Location.X + 22, ptemp.Location.Y - 1)
End With
With l_desc
.Text = description.Replace("CYL ASSY", "")
.ForeColor = Color.Black
.Font = New Font(Font.Name, 5.5, FontStyle.Regular)
.AutoSize = True
.Location = New Point(ptemp.Location.X + 1, ptemp.Location.Y + 13)
End With
With l_date
.Text = shed_date.ToString("M/d")
.ForeColor = Color.Black
.AutoSize = True
.Font = New Font(Font.Name, 7)
.Location = New Point(ptemp.Location.X - 2, ptemp.Location.Y - 1)
End With
If run_qty = "" Then run_qty = 123
With l_qty
.Text = run_qty & "/" & total_qty
.ForeColor = Color.Black()
.BackColor = Color.White
.AutoSize = True
.RightToLeft = Windows.Forms.RightToLeft.Inherit
.Location = New Point(ptemp.Location.X + 27, ptemp.Location.Y + 21)
.Font = New Font(Font.Name, 7)
.TextAlign = ContentAlignment.MiddleCenter
End With
If part_number <> "" Then
ptemp.Controls.Add(l_part_num)
ptemp.Controls.Add(l_date)
ptemp.Controls.Add(l_desc)
ptemp.Controls.Add(l_qty)
ptemp.Tag = job_number & "~" & item_number & "~" & part_number
ptemp.Width = temp_panel.Width - 5
ptemp.Height = 34
ptemp.BorderStyle = BorderStyle.None
ptemp.BackColor = Color.Yellow
AddHandler ptemp.Click, AddressOf Ptemp_Click
AddHandler l_desc.Click, AddressOf Ptemp_Click
AddHandler l_qty.Click, AddressOf Ptemp_Click
AddHandler l_part_num.Click, AddressOf Ptemp_Click
AddHandler l_date.Click, AddressOf Ptemp_Click
Else
ptemp.Tag = "0"
ptemp.Width = temp_panel.Width
ptemp.Height = 34
ptemp.BorderStyle = BorderStyle.None
ptemp.BackColor = Color.Transparent
End If
temp_panel.Controls.Add(ptemp)
End If
End Sub
Change:
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number)
To:
If Me.InvokeRequired Then
Me.Invoke(New delegate_panel(AddressOf delegate_panel_build), New Object() {job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number})
If Me.InvokeRequired Then
Dim objdele As delegate_panel
objdele = AddressOf delegate_panel_build
objdele.Invoke(job_number,
To:
If Me.InvokeRequired Then
Me.Invoke(New delegate_panel(AddressOf delegate_panel_build), New Object() {job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number})
ASKER
Tried that as well and it just keeps thinking nothing happens.
ASKER
When the program tries to execute this line of code, the thread just locks up and nothing happens, any ideas? Am I still not invoking the the delegate property.
Me.Invoke(New delegate_panel(AddressOf delegate_panel_build), New Object() {job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number})
Me.Invoke(New delegate_panel(AddressOf delegate_panel_build), New Object() {job_number, item_number, description, shed_date, total_qty, run_qty, temp_panel, part_number})
I haven't studied your code...I'll take a CLOSER look later...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Nice,
It looks like it worked. Could you explain these 2 procedures I am not familiar with the Action delegate, is that new?
I am not familiar
Sub start_progress()
If Me.InvokeRequired Then
Dim dele As Action
dele = AddressOf start_progress
Me.Invoke(dele)
Else
ss_progress_bar.Style = ProgressBarStyle.Marquee
End If
End Sub
Sub stop_progress()
If Me.InvokeRequired Then
Dim dele As Action
dele = AddressOf start_progress
Me.Invoke(dele)
Else
ss_progress_bar.Style = ProgressBarStyle.Blocks
End If
End Sub
It looks like it worked. Could you explain these 2 procedures I am not familiar with the Action delegate, is that new?
I am not familiar
Sub start_progress()
If Me.InvokeRequired Then
Dim dele As Action
dele = AddressOf start_progress
Me.Invoke(dele)
Else
ss_progress_bar.Style = ProgressBarStyle.Marquee
End If
End Sub
Sub stop_progress()
If Me.InvokeRequired Then
Dim dele As Action
dele = AddressOf start_progress
Me.Invoke(dele)
Else
ss_progress_bar.Style = ProgressBarStyle.Blocks
End If
End Sub
They just use Maquee mode, which keeps the progress bar moving all the time. When the long-running process starts it puts the bar into Marquee mode, when it's done it puts it back into regular mode.
As far as the Action delegate goes,
http://msdn.microsoft.com/en-us/library/system.action.aspx
"Encapsulates a method that takes no parameters and does not return a value."
As far as the Action delegate goes,
http://msdn.microsoft.com/en-us/library/system.action.aspx
"Encapsulates a method that takes no parameters and does not return a value."
ASKER
The stop_process is not working, the progress bar never leaves marquee mode.
ASKER
I got the stop_process working, but now I need to execute the worker thread every halfhour.
ASKER
Ok, i thought I had everything working, I created a timer thread that runs every 10 seconds. It was working fine but I watched it for a while, then all of a sudden i got this error: Error Creating Window Handle, what is this?
I increased the points because this was a lot more work then I initionally thought.
I increased the points because this was a lot more work then I initionally thought.
Dim duetime As New TimeSpan(0, 0, 1) 'how long to wait before starting timer
Dim ticktime As New TimeSpan(0, 0, 0, 0, 10000) 'Number of seconds in milleseconds between each tick
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim frm_login As New Login
frm_login.ShowDialog()
If login_status Then
thtimer = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf build_query), Nothing, duetime, ticktime)
End If
End Sub
ASKER
Figured out that it loops through 9 times, then it crashes. Do i need to do some cleanup?
ASKER
Getting closer here, I found out that i basically need to do some garbage cleanup before creating all the new panels. I created a loop that should go through and dispose of all existing controls before creating new ones. I can't quite get it to work and I am not sure where I should put the procedure call
Sub clear_controls(ByVal ctrl As Control)
Dim frmctrl As Control
Dim flow_p_controls As Control
For Each frmctrl In ctrl.Controls
If TypeOf frmctrl Is FlowLayoutPanel Then
If frmctrl.HasChildren Then
For Each flow_p_controls In frmctrl.Controls
flow_p_controls.Dispose()
Next
End If
End If
If frmctrl.HasChildren Then
clear_controls(frmctrl)
End If
Next
End Sub
I found this very helpful, thx.
Open in new window