|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Newbie help: How to detect when a worker thread ihas completed normalyOn the main UI several controls are disabled and sevral variables are set BEFORE the background thread is started I would like to renabled those controls and reset those variables after the background thread is finished. I could see using the control.invoke. but with the number of controls and variables I would just like to call a seperate sub that renables the controls like the one that disables them Thread.join (as I understand it) won't work as I do not want to lock the form. Events won't (I could be wrong) because they are raised on the same background thread (again the UI controls) I'm thinking I must use a timer control to check if the background thread is still running. If that works then fine But is there there another way? Bottom line: when a worker thread started by the UI is done how can I trigger a procedure in the UI? Thank you JL, it depends on how you are doing the threading. Here is some code
that will work using the new BackgroundWorker object: Imports system.ComponentModel 'This is where BackgroundWorker is Public Class Form1 'Make sure you Dim WithEvents Dim WithEvents myBackgroundWorker As BackgroundWorker Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Disable the controls that we will enable later btnMain.Enabled = False End Sub Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click 'Create a new instance myBackgroundWorker = New BackgroundWorker ' Start the thread. This fires the Do_Work event (see below) myBackgroundWorker.RunWorkerAsync() End Sub Private Sub myBackgroundWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles myBackgroundWorker.DoWork 'This is where the code goes for your worker thread to do all its work End Sub Private Sub myBackgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles myBackgroundWorker.RunWorkerCompleted 'This event fires when the Worker is completed so enable the controls btnMain.enabled = True End Sub End Class Does that help? Eric B J*@JL.com wrote: Show quoteHide quote > for VB 2005 > > On the main UI several controls are disabled and sevral variables are > set BEFORE the background thread is started > > I would like to renabled those controls and reset those variables > after the background thread is finished. > > I could see using the control.invoke. but with the number of controls > and variables I would just like to call a seperate sub that renables > the controls like the one that disables them > > Thread.join (as I understand it) won't work as I do not want to lock > the form. > Events won't (I could be wrong) because they are raised on the same > background thread (again the UI controls) > > I'm thinking I must use a timer control to check if the background > thread is still running. > > If that works then fine > But is there there another way? > > Bottom line: when a worker thread started by the UI is done how can I > trigger a procedure in the UI? > > > Thank you Create a windows application project and add one button to Form1,
leaving the name of the button as button1. Then replace the Form1.vb with the code below. I think this will do what you are looking for. Clicking the button will start a thread. Inside the thread a call is made to a method of the Form, in this case it simply opens a msgbox. After a 3 second delay, simulating some work, the thread calls a second method in the form, passing a single string parameter which again simply opens a msgbox. Imports System.Threading Public Class Form1 Private Shared GUI As Form1 = Nothing Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load GUI = Me End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim Button1ClickThread As New Thread(AddressOf ThreadFunction) Button1ClickThread.Start() End Sub Private Delegate Sub ThreadStartedDelegate() Private Sub ThreadStarted() 'Do some thread started gui work here MsgBox("Thread Started") End Sub Private Delegate Sub ThreadStoppedDelegate(ByVal Parameter As String) Private Sub ThreadStopped(ByVal Parameter As String) 'Do some thread stopped gui work here MsgBox("Thread Stopped [" + Parameter + "]") End Sub Private Sub ThreadFunction() Dim ThreadStartedFunction As New ThreadStartedDelegate(AddressOf GUI.ThreadStarted) GUI.Invoke(ThreadStartedFunction) Thread.Sleep(3000) Dim ThreadStoppedFunction As New ThreadStoppedDelegate(AddressOf ThreadStopped) GUI.Invoke(ThreadStoppedFunction, "Feels good") End Sub End Class J*@JL.com wrote: Show quoteHide quote > for VB 2005 > > On the main UI several controls are disabled and sevral variables are > set BEFORE the background thread is started > > I would like to renabled those controls and reset those variables > after the background thread is finished. > > I could see using the control.invoke. but with the number of controls > and variables I would just like to call a seperate sub that renables > the controls like the one that disables them > > Thread.join (as I understand it) won't work as I do not want to lock > the form. > Events won't (I could be wrong) because they are raised on the same > background thread (again the UI controls) > > I'm thinking I must use a timer control to check if the background > thread is still running. > > If that works then fine > But is there there another way? > > Bottom line: when a worker thread started by the UI is done how can I > trigger a procedure in the UI? > > > Thank you Thank you both for taking the time to respond.
I should have posted my the code so so you two could see where I'm coming from, sorry about that. Some background on the actual program I wrote and want to change: I already wrote( for personal use) a program that uses the background component. While this proram runs fine I want better control/options of the background thread so I want to use the system.thread way of doing it. Most of the processing are done in several modules which may be used seperately or done one after the other though only one background run at a time. All of these modules have programs that will display information in the main UI while running. The "testbutton" only purpose is to represent several controls (from the program mentioned above) that are disabled and must be reenabled after the background thread ends. So I wrote this test project to help me undertstand delegates and control.invoke updates. It is written to basically emulate how the actual program works when it comes to updating the controls. I used someone else's code on the internet, I removed the extra stuff and made some changes so it reflects how I need to update the textbox. Like the main program this code will: 1) start a background process at the button click. The sub that is run is in a module where it must stay. 2) As the thread runs the sub will update the main form by * sending the text to be displayed *sending a control code (represented initially by the ctr variable) *pausing the worker thread. Pausing takes place in the worker thread and the pause duration will vary 3) repeat til done Now that the updating part works, what I need now is to alert the main UI that the thread is completed so the main UI does the reenabling of the controls. So after the thread that runs the "startprocess" is completed, how do I trigger the main UI to call the enablebuttons() sub? I see only doing a series of control.invokes if the only way is to have the background thread be the trigger. Please let me know if both your sample codes will still work now that I presented the test code. Thank you both very much for helping. ------------------------------------------------ Imports System.Threading Public Class Form1 Dim xctr As Integer Private Delegate Sub UpDateGSLDelegate(ByVal txt As String, ByVal rpn As Integer) Public Sub updateTxtBox(ByVal txt As String, ByVal rpn As Integer) If txtBoxtest.InvokeRequired Then Invoke(New UpDateGSLDelegate(AddressOf UpDateTheGSL), txt, rpn) Else UpDateTheGSL(txt, rpn) End If End Sub Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click Dim t1 As New System.Threading.Thread(AddressOf startproces) testbutton.Enabled = False t1.Start() End Sub Private Sub enablebuttons() testbuttont.Enabled = True End Sub Public Sub UpDateTheGSL(ByVal txt As String, ByVal rpn As Integer) txtBoxtest.Text = txt & rpn End Sub Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed MainForm = Nothing End Sub Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load MainForm = Me End Sub End Class ---------------------------------------------- Module Module2 Public MainForm As Form1 Public Sub startProcess() For ctr As Integer = 0 To 5 UpdateMainForm("kkjkjkjk", ctr, 1000) Next End Sub Sub UpdateMainForm(ByVal txt As String, ByVal rpn As Integer, ByVal xsleep As Integer) MainForm.updateTxtBox(txt, rpn) System.Threading.Thread.Sleep(xsleep) End Sub End Module The example I provided contains a thread that calls a method of the
main UI when it stops. In the example, the thread will call the Form1 sub routine named "ThreadStopped". The ThreadStopped sub routine can freely interact with the Form and therefore can easily enable controls. It makes no difference where the thread function resides. If the thread is in another module then you would need to reference the GUI object with "Form1.GUI" rather than just GUI. Here is the original call made at the end of the thread's execution: Dim ThreadStoppedFunction As New ThreadStoppedDelegate(AddressOf ThreadStopped) GUI.Invoke(ThreadStoppedFunction, "Feels good") If the thread were running in another module, this code would need to look like: Dim ThreadStoppedFunction As New ThreadStoppedDelegate(AddressOf Form1.GUI.ThreadStopped) Fomr1.GUI.Invoke(ThreadStoppedFunction, "Feels good") If you are starting multiple threads and you need to know when they all have completed, then you will need to more work, such as implementing a semaphore or use events and WaitAll (as examples). J*@JL.com wrote: Show quoteHide quote > Thank you both for taking the time to respond. > I should have posted my the code so so you two could see where I'm > coming from, sorry about that. > > Some background on the actual program I wrote and want to change: > I already wrote( for personal use) a program that uses the background > component. While this proram runs fine I want better control/options > of the background thread so I want to use the system.thread way of > doing it. > > Most of the processing are done in several modules which may be used > seperately or done one after the other though only one background run > at a time. All of these modules have programs that will display > information in the main UI while running. > > The "testbutton" only purpose is to represent several controls (from > the program mentioned above) that are disabled and must be reenabled > after the background thread ends. > > So I wrote this test project to help me undertstand delegates and > control.invoke updates. It is written to basically emulate how the > actual program works when it comes to updating the controls. I used > someone else's code on the internet, I removed the extra stuff and > made some changes so it reflects how I need to update the textbox. > > Like the main program this code will: > 1) start a background process at the button click. > The sub that is run is in a module where it must stay. > 2) As the thread runs the sub will update the main form by > * sending the text to be displayed > *sending a control code (represented initially by the ctr > variable) > *pausing the worker thread. Pausing takes place in the worker > thread and the pause duration will vary > > 3) repeat til done > > > Now that the updating part works, what I need now is to alert the main > UI that the thread is completed so the main UI does the reenabling of > the controls. > > So after the thread that runs the "startprocess" is completed, how do > I trigger the main UI to call the enablebuttons() sub? > > I see only doing a series of control.invokes if the only way is to > have the background thread be the trigger. > > Please let me know if both your sample codes will still work now that > I presented the test code. > > Thank you both very much for helping. > > ------------------------------------------------ > > Imports System.Threading > Public Class Form1 > Dim xctr As Integer > Private Delegate Sub UpDateGSLDelegate(ByVal txt As String, ByVal > rpn As Integer) > > Public Sub updateTxtBox(ByVal txt As String, ByVal rpn As Integer) > If txtBoxtest.InvokeRequired Then > Invoke(New UpDateGSLDelegate(AddressOf UpDateTheGSL), txt, > rpn) > Else > UpDateTheGSL(txt, rpn) > End If > End Sub > > Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As > System.EventArgs) Handles btnStart.Click > Dim t1 As New System.Threading.Thread(AddressOf startproces) > testbutton.Enabled = False > t1.Start() > End Sub > > Private Sub enablebuttons() > testbuttont.Enabled = True > End Sub > Public Sub UpDateTheGSL(ByVal txt As String, ByVal rpn As Integer) > txtBoxtest.Text = txt & rpn > End Sub > > Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As > System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed > MainForm = Nothing > End Sub > Private Sub Form1_Load(ByVal sender As Object, ByVal e As > System.EventArgs) Handles Me.Load > MainForm = Me > End Sub > End Class > > ---------------------------------------------- > Module Module2 > Public MainForm As Form1 > > Public Sub startProcess() > For ctr As Integer = 0 To 5 > UpdateMainForm("kkjkjkjk", ctr, 1000) > Next > End Sub > > Sub UpdateMainForm(ByVal txt As String, ByVal rpn As Integer, > ByVal xsleep As Integer) > MainForm.updateTxtBox(txt, rpn) > System.Threading.Thread.Sleep(xsleep) > End Sub > End Module Thank you!!!!
This is what I needed! On 28 Nov 2006 16:43:41 -0800, "FishingScout" <fishingsc***@comcast.net> wrote: Show quoteHide quote > >The example I provided contains a thread that calls a method of the >main UI when it stops. In the example, the thread will call the Form1 >sub routine named "ThreadStopped". The ThreadStopped sub routine can >freely interact with the Form and therefore can easily enable controls. > It makes no difference where the thread function resides. If the >thread is in another module then you would need to reference the GUI >object with "Form1.GUI" rather than just GUI. Here is the original >call made at the end of the thread's execution: > > Dim ThreadStoppedFunction As New >ThreadStoppedDelegate(AddressOf ThreadStopped) > GUI.Invoke(ThreadStoppedFunction, "Feels good") > >If the thread were running in another module, this code would need to >look like: > > Dim ThreadStoppedFunction As New >ThreadStoppedDelegate(AddressOf Form1.GUI.ThreadStopped) > Fomr1.GUI.Invoke(ThreadStoppedFunction, "Feels good") > > >If you are starting multiple threads and you need to know when they all >have completed, then you will need to more work, such as implementing a >semaphore or use events and WaitAll (as examples). > >J*@JL.com wrote: >> Thank you both for taking the time to respond. >> I should have posted my the code so so you two could see where I'm >> coming from, sorry about that. >> >> Some background on the actual program I wrote and want to change: >> I already wrote( for personal use) a program that uses the background >> component. While this proram runs fine I want better control/options >> of the background thread so I want to use the system.thread way of >> doing it. >> >> Most of the processing are done in several modules which may be used >> seperately or done one after the other though only one background run >> at a time. All of these modules have programs that will display >> information in the main UI while running. >> >> The "testbutton" only purpose is to represent several controls (from >> the program mentioned above) that are disabled and must be reenabled >> after the background thread ends. >> >> So I wrote this test project to help me undertstand delegates and >> control.invoke updates. It is written to basically emulate how the >> actual program works when it comes to updating the controls. I used >> someone else's code on the internet, I removed the extra stuff and >> made some changes so it reflects how I need to update the textbox. >> >> Like the main program this code will: >> 1) start a background process at the button click. >> The sub that is run is in a module where it must stay. >> 2) As the thread runs the sub will update the main form by >> * sending the text to be displayed >> *sending a control code (represented initially by the ctr >> variable) >> *pausing the worker thread. Pausing takes place in the worker >> thread and the pause duration will vary >> >> 3) repeat til done >> >> >> Now that the updating part works, what I need now is to alert the main >> UI that the thread is completed so the main UI does the reenabling of >> the controls. >> >> So after the thread that runs the "startprocess" is completed, how do >> I trigger the main UI to call the enablebuttons() sub? >> >> I see only doing a series of control.invokes if the only way is to >> have the background thread be the trigger. >> >> Please let me know if both your sample codes will still work now that >> I presented the test code. >> >> Thank you both very much for helping. >> >> ------------------------------------------------ >> >> Imports System.Threading >> Public Class Form1 >> Dim xctr As Integer >> Private Delegate Sub UpDateGSLDelegate(ByVal txt As String, ByVal >> rpn As Integer) >> >> Public Sub updateTxtBox(ByVal txt As String, ByVal rpn As Integer) >> If txtBoxtest.InvokeRequired Then >> Invoke(New UpDateGSLDelegate(AddressOf UpDateTheGSL), txt, >> rpn) >> Else >> UpDateTheGSL(txt, rpn) >> End If >> End Sub >> >> Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As >> System.EventArgs) Handles btnStart.Click >> Dim t1 As New System.Threading.Thread(AddressOf startproces) >> testbutton.Enabled = False >> t1.Start() >> End Sub >> >> Private Sub enablebuttons() >> testbuttont.Enabled = True >> End Sub >> Public Sub UpDateTheGSL(ByVal txt As String, ByVal rpn As Integer) >> txtBoxtest.Text = txt & rpn >> End Sub >> >> Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As >> System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed >> MainForm = Nothing >> End Sub >> Private Sub Form1_Load(ByVal sender As Object, ByVal e As >> System.EventArgs) Handles Me.Load >> MainForm = Me >> End Sub >> End Class >> >> ---------------------------------------------- >> Module Module2 >> Public MainForm As Form1 >> >> Public Sub startProcess() >> For ctr As Integer = 0 To 5 >> UpdateMainForm("kkjkjkjk", ctr, 1000) >> Next >> End Sub >> >> Sub UpdateMainForm(ByVal txt As String, ByVal rpn As Integer, >> ByVal xsleep As Integer) >> MainForm.updateTxtBox(txt, rpn) >> System.Threading.Thread.Sleep(xsleep) >> End Sub >> End Module HOLD THE PHONE!!
I thought of this after I posted the below post! I tried something and it works. I added the code below with the asterisks to make the added code stand out. it does what I need, the background thread will simply send another string with a specific value at the end and terminate as normal and the mainform UI txtBoxtest_TextChanged event does the rest independently. Is there a way to create a raise event that does the same thing in the same matter more or less? Again, thank you both On Tue, 28 Nov 2006 18:12:43 -0600, J*@JL.com wrote: Show quoteHide quote >Thank you both for taking the time to respond. *** Private Sub txtBoxtest_TextChanged(ByVal sender As Object, ByVal e>I should have posted my the code so so you two could see where I'm >coming from, sorry about that. > >Some background on the actual program I wrote and want to change: >I already wrote( for personal use) a program that uses the background >component. While this proram runs fine I want better control/options >of the background thread so I want to use the system.thread way of >doing it. > >Most of the processing are done in several modules which may be used >seperately or done one after the other though only one background run >at a time. All of these modules have programs that will display >information in the main UI while running. > >The "testbutton" only purpose is to represent several controls (from >the program mentioned above) that are disabled and must be reenabled >after the background thread ends. > >So I wrote this test project to help me undertstand delegates and >control.invoke updates. It is written to basically emulate how the >actual program works when it comes to updating the controls. I used >someone else's code on the internet, I removed the extra stuff and >made some changes so it reflects how I need to update the textbox. > >Like the main program this code will: >1) start a background process at the button click. > The sub that is run is in a module where it must stay. >2) As the thread runs the sub will update the main form by > * sending the text to be displayed > *sending a control code (represented initially by the ctr > variable) > *pausing the worker thread. Pausing takes place in the worker > thread and the pause duration will vary > > 3) repeat til done > > >Now that the updating part works, what I need now is to alert the main >UI that the thread is completed so the main UI does the reenabling of >the controls. > >So after the thread that runs the "startprocess" is completed, how do >I trigger the main UI to call the enablebuttons() sub? > >I see only doing a series of control.invokes if the only way is to >have the background thread be the trigger. > >Please let me know if both your sample codes will still work now that >I presented the test code. > >Thank you both very much for helping. > >------------------------------------------------ > >Imports System.Threading >Public Class Form1 > Dim xctr As Integer > Private Delegate Sub UpDateGSLDelegate(ByVal txt As String, ByVal >rpn As Integer) > > Public Sub updateTxtBox(ByVal txt As String, ByVal rpn As Integer) > If txtBoxtest.InvokeRequired Then > Invoke(New UpDateGSLDelegate(AddressOf UpDateTheGSL), txt, >rpn) > Else > UpDateTheGSL(txt, rpn) > End If > End Sub > > Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As >System.EventArgs) Handles btnStart.Click > Dim t1 As New System.Threading.Thread(AddressOf startproces) > testbutton.Enabled = False > t1.Start() > End Sub > > Private Sub enablebuttons() > testbuttont.Enabled = True > End Sub > Public Sub UpDateTheGSL(ByVal txt As String, ByVal rpn As Integer) > txtBoxtest.Text = txt & rpn > End Sub > > Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As >System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed > MainForm = Nothing > End Sub > Private Sub Form1_Load(ByVal sender As Object, ByVal e As >System.EventArgs) Handles Me.Load > MainForm = Me > End Sub As System.EventArgs) Handles txtBoxtest.TextChanged If txtBoxtest.Text = "" Then Me.enablebuttons() End If End Sub >End Class **** UpdateMainForm("", 0, 10)> >---------------------------------------------- >Module Module2 > Public MainForm As Form1 > > Public Sub startProcess() > For ctr As Integer = 0 To 5 > UpdateMainForm("kkjkjkjk", ctr, 1000) > Nex Show quoteHide quote > End Sub > > Sub UpdateMainForm(ByVal txt As String, ByVal rpn As Integer, >ByVal xsleep As Integer) > MainForm.updateTxtBox(txt, rpn) > System.Threading.Thread.Sleep(xsleep) > End Sub >End Module
word automation vb.net
Arranging window screens on multi-monitor Desktop set refresh rate for an active browser window better way to program than this? newbie syntax question: adding event handler for button not working How broad should an interface be? Advice needed. File and Database Search Re: Is VB.NET Stable?? Error on deleting registry value sqlDataReader does not return correct sorted data |
|||||||||||||||||||||||