Results 1 to 10 of 10

Thread: [RESOLVED] Thread Form and Owner

  1. #1

    Thread Starter
    Frenzied Member mickey_pt's Avatar
    Join Date
    Sep 2006
    Location
    Corner of the Europe :)
    Posts
    1,959

    Resolved [RESOLVED] Thread Form and Owner

    Hi
    I have a little form that has to do a time consuming job, so the correct way to tell the user that the process it's running it's using a progress bar...
    So i decided to create a new form with 2 labels and a progress bar, to show over the little window, that show a title the progress and the number of lines already processed.

    Everything is working, except the Z order of this form, i can set the form to be top most, but this is not the correct way, so i think that the correct way it's setting the owner of this new form. The only problem it's the cross threaded exceptions.

    How can i set the owner of the form without the exceptions?
    Should i look to the CheckForIllegalCrossThreadCalls?

    vb.net Code:
    1. Dim maxVal As Integer = 30
    2.         Dim newForm As New FormProgress()
    3.         Dim newThr As New Threading.Thread(AddressOf newForm.ShowDialog)
    4.         newThr.Start()
    5.         newForm.SetMaxValue(maxVal) 'Set the progress var
    6.         newForm.SetTitle("Test title...")
    7.         For i As Integer = 1 To maxVal
    8.             Threading.Thread.Sleep(500)
    9.             newForm.SetCurrentValue(i)
    10.         Next
    11.         newForm.CloseForm()

    Rate People That Helped You
    Mark Thread Resolved When Resolved

  2. #2
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Thread Form and Owner

    There can only be 1 UI thread per application. That's the only thread where you can use the methods and properties of forms and form controls. So it's the time-consuming job that belongs in a separate thread, not the progress bar. A convenient way to report progress from a processing thread is with a BackgroundWorker. Here's how you could code it:
    Code:
    	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click		
    		BackgroundWorker1.WorkerReportsProgress = True
    		BackgroundWorker1.RunWorkerAsync()
    		newForm.Show(Me)
    	End Sub
    
    	Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
                    'here's your time consuming process
    		For i As Integer = 1 To maxValue
    			Threading.Thread.Sleep(500)
    			Dim progress As Integer = CInt(i * 100 / maxValue)
    			BackgroundWorker1.ReportProgress(progress)
    		Next
    	End Sub
    
    	Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
                   'This event is raised on the UI thread when progress is reported:
    		newForm.SetCurrentValue(e.ProgressPercentage)
    	End Sub
    
    	Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    		newForm.Hide()
    	End Sub
    Progress is reported as a percentage, so you may need to adjust your SetCurrentValue sub accordingly. Note that I use Show(Me) to show an Owned Form. This allows the user to continue doing things on the main form while the progress form is showing. You can't do that with ShowDialog.

    BB

  3. #3

    Thread Starter
    Frenzied Member mickey_pt's Avatar
    Join Date
    Sep 2006
    Location
    Corner of the Europe :)
    Posts
    1,959

    Re: Thread Form and Owner

    Thanks boops boops

    I know how to use the background worker and that's not what i intend to do...

    The main form should remain blocked, it's a critical operation, so i need someway to tell the user that the operation it's running.
    Like i wrote i can make the form the top most, but then it'll be over other applications and i don't like that.
    The other option by setting the owner of the form, i can bypass the cross thread error, setting the CheckForIllegalCrossThreadCalls = False, before starting the new thread and then everything works fine... I just don't want to use this, but if there isn't any other way...

    Thanks

    Rate People That Helped You
    Mark Thread Resolved When Resolved

  4. #4

    Thread Starter
    Frenzied Member mickey_pt's Avatar
    Join Date
    Sep 2006
    Location
    Corner of the Europe :)
    Posts
    1,959

    Re: Thread Form and Owner

    * Duplicated Post *
    Last edited by mickey_pt; Dec 10th, 2013 at 01:04 PM. Reason: Duplciated....

    Rate People That Helped You
    Mark Thread Resolved When Resolved

  5. #5
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Thread Form and Owner

    Quote Originally Posted by boops boops View Post
    There can only be 1 UI thread per application. That's the only thread where you can use the methods and properties of forms and form controls.
    That's not strictly true. You can perform UI operations on any thread. The restriction is that you can only access the handle of a control on the thread that created it. We use the term "UI thread" to refer to the thread on which the application's startup form is created because that's the thread that almost all UI operations are performed. If you create a splash screen in your app though, it is created on a different thread, which is how it can be displayed while the startup form is still being created.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Thread Form and Owner

    Quote Originally Posted by mickey_pt View Post
    Thanks boops boops

    I know how to use the background worker and that's not what i intend to do...

    The main form should remain blocked, it's a critical operation, so i need someway to tell the user that the operation it's running.
    Like i wrote i can make the form the top most, but then it'll be over other applications and i don't like that.
    The other option by setting the owner of the form, i can bypass the cross thread error, setting the CheckForIllegalCrossThreadCalls = False, before starting the new thread and then everything works fine... I just don't want to use this, but if there isn't any other way...

    Thanks
    A BackgroundWorker is perfect for this... if you use it properly. What you can do is design a form that has a ProgressBar on it and contains a BackgroundWorker. You then declare a constructor in that form that takes a DoWorkEventHandler delegate as an argument. In your main form, you write a DoWork event handler but without a Handles clause and when you create the progress form you pass a delegate for that method to it. That method is then used as the handler for the DoWork event of the BackgroundWorker in the progress form. E.g.
    vb.net Code:
    1. Imports System.Threading
    2. Imports System.ComponentModel
    3.  
    4. Public Class MainForm
    5.  
    6.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7.         Using dialogue As New WorkingDialogue(AddressOf BackgroundWorker_DoWork)
    8.             dialogue.ShowDialog()
    9.         End Using
    10.  
    11.         MessageBox.Show("Task complete")
    12.     End Sub
    13.  
    14.     Private Sub BackgroundWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    15.         Dim worker = DirectCast(sender, BackgroundWorker)
    16.  
    17.         For i = 1 To 100
    18.             Thread.Sleep(100)
    19.             worker.ReportProgress(i)
    20.         Next
    21.     End Sub
    22.  
    23. End Class
    vb.net Code:
    1. Imports System.ComponentModel
    2.  
    3. Public Class WorkingDialogue
    4.  
    5.     Public Sub New(doWorkHandler As DoWorkEventHandler)
    6.         ' This call is required by the designer.
    7.         InitializeComponent()
    8.  
    9.         ' Add any initialization after the InitializeComponent() call.
    10.  
    11.         AddHandler Me.BackgroundWorker1.DoWork, doWorkHandler
    12.     End Sub
    13.  
    14.     Private Sub WorkingDialogue_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    15.         Me.BackgroundWorker1.RunWorkerAsync()
    16.     End Sub
    17.  
    18.     Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    19.         Me.ProgressBar1.Value = e.ProgressPercentage
    20.     End Sub
    21.  
    22.     Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    23.         Me.Close()
    24.     End Sub
    25. End Class
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Frenzied Member mickey_pt's Avatar
    Join Date
    Sep 2006
    Location
    Corner of the Europe :)
    Posts
    1,959

    Re: Thread Form and Owner

    THanks JMC for yout time.
    Always thinking outside the box...

    But it have one problem, I can't make it to work, did you tested your code? It looks like it ignores the Sleep, or in my case the time consumption operation...
    Sorry

    Rate People That Helped You
    Mark Thread Resolved When Resolved

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Thread Form and Owner

    Yep, tested and passed. Is the DoWork event handler being executed? If not then you need to determine why not. If so then there's obviously something wrong with your code in that event handler. Post exactly what you're using.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  9. #9

    Thread Starter
    Frenzied Member mickey_pt's Avatar
    Join Date
    Sep 2006
    Location
    Corner of the Europe :)
    Posts
    1,959

    Re: Thread Form and Owner

    Hi
    I just created a new project and write everything like in the sample code... The only difference was the form name and the proc name for the delegate...

    Anyway:
    vb.net Code:
    1. Imports System.Threading
    2. Imports System.ComponentModel
    3.  
    4. Public Class Form1
    5.  
    6.     Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    7.         Using frrrr As New Form2(AddressOf doWork)
    8.             frrrr.ShowDialog()
    9.         End Using
    10.         MsgBox("Work is done!", MsgBoxStyle.Information)
    11.     End Sub
    12.  
    13.     Private Sub doWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    14.         Dim worker = DirectCast(sender, BackgroundWorker)
    15.         For i As Integer = 1 To 100
    16.             Thread.Sleep(1000)
    17.             worker.ReportProgress(i)
    18.         Next
    19.  
    20.     End Sub
    21. End Class

    vb.net Code:
    1. Imports System.ComponentModel
    2. Public Class Form2
    3.     Public Sub New(doWork As DoWorkEventHandler)
    4.  
    5.         ' This call is required by the designer.
    6.         InitializeComponent()
    7.  
    8.         ' Add any initialization after the InitializeComponent() call.
    9.         AddHandler Me.BackgroundWorker1.DoWork, doWork
    10.     End Sub
    11.  
    12.  
    13.     Private Sub Form2_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    14.         BackgroundWorker1.RunWorkerAsync()
    15.     End Sub
    16.  
    17.  
    18.     Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    19.         ProgressBar1.Value = e.ProgressPercentage
    20.     End Sub
    21.  
    22.  
    23.     Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    24.         Me.Close()
    25.     End Sub
    26. End Class

    Rate People That Helped You
    Mark Thread Resolved When Resolved

  10. #10

    Thread Starter
    Frenzied Member mickey_pt's Avatar
    Join Date
    Sep 2006
    Location
    Corner of the Europe :)
    Posts
    1,959

    Re: Thread Form and Owner

    Oh...
    Forgot the ReportProgress property... Change it to True, and now it works! :/

    THanks

    Rate People That Helped You
    Mark Thread Resolved When Resolved

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width