Results 1 to 17 of 17

Thread: [RESOLVED] Background Worker & Progress (reporting to the default instance of the main form)

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Resolved [RESOLVED] Background Worker & Progress (reporting to the default instance of the main form)

    I am using background worker to report progress on the screen.
    In the Main.vb I have the following code:
    Code:
        Public Sub report(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bwlistener.ProgressChanged
            Dim message As String = e.UserState
            logRTB.AppendText(message & vbCrLf)
        End Sub
    When I call this from Main.vb I use:
    Code:
    bwlistener.ReportProgress(0, "Some status text goes here")
    It works great.

    The problem is when I try to call it from any other module in my project.

    When I call it OtherFile.vb:
    Code:
    Main.bwlistener.ReportProgress(0, "Some status text goes here")
    It doesn't work... The program doesn't crash. Debug goes through everything but no output is actually shown to the end user.

    Why would it not work?
    Any ideas?
    Thanks!
    Last edited by marcellus; Jun 8th, 2012 at 04:08 PM. Reason: Updated the title to reflect better the topic of the thread.

  2. #2
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: Background Worker not Reporting Progress

    How have you declared Main.vb ? Is this a form, a class? If a form, are you sure you are not using the default instance (if you have any idea what that is)?

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker not Reporting Progress

    Quote Originally Posted by Grimfort View Post
    How have you declared Main.vb ? Is this a form, a class? If a form, are you sure you are not using the default instance (if you have any idea what that is)?
    It's a form where I am displaying the text reported to the background worker.
    I don't know what the default instance is... I have only 1 form in this program (main.vb).
    What information do you need? or how can I find it...
    Thanks!!

  4. #4
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: Background Worker not Reporting Progress

    A bit-o-googling will tell you what they are. When your app starts, if you are using the form as your startup object, it will create a COPY (instance) of the form. However, calling Main.xxx will be calling the default (and a new COPY the first time you do this) instance, so basically a second copy, not the one you are "working" with. It is a feature M$ added to make things easier for new developers, which actually just confuses them imo.

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker not Reporting Progress

    So if I would create a separate form (not the starting one) and report that one instead of the main.vb then it should work fine?

  6. #6
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: Background Worker not Reporting Progress

    Yes, but that is not what you are trying to do, you would then have 2 forms. All you have to do, instead of using the default instance of Main, is to find the one you want to update. You can do this a couple of ways, the first by setting a global variable during the form load event, or second by searching for it the forms collection.

    Friend TheMainForm As Main << inside a module or something


    Sub FormLoad
    TheMainForm = Me
    End Sub

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker not Reporting Progress

    Thank you for your help but I still cannot figure this one out.
    I've read the following article but unfortunately I still cannot get this one working.

    The project has one form (Form1) with one textbox in the middle (TextBox1).
    Below is the code for both files:

    Form1.vb:
    Code:
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            showTest()
            Module1.showTestFromModule1()
        End Sub
    
        Private Sub showTest()
            BackgroundWorker1.ReportProgress(0, "This shows on the main form.")
        End Sub
    
        Private Sub progress(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            Dim message As String = e.UserState
            TextBox1.AppendText(message & vbCrLf)
        End Sub
    
    End Class
    Module1.vb:
    Code:
    Module Module1
    
        Public Sub showTestFromModule1()
            Form1.BackgroundWorker1.ReportProgress(0, "This doesn't show up on the main form.")
        End Sub
    
    End Module
    Basically I want the Sub From Module1 be able to report to the backgroundworker1 on the main form.
    Last edited by marcellus; Jun 8th, 2012 at 03:06 PM. Reason: added last line

  8. #8
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Background Worker not Reporting Progress

    because the module is using the default instance of the form... which you can't guarantee that you're even using... so it's reporting progress over there...

    You may want to re-think your strategy... why are you trying to show progress from something in the module? I'd also ask why a module, but that's not really relevant to the problem at hand.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker not Reporting Progress

    Quote Originally Posted by techgnome View Post
    You may want to re-think your strategy... why are you trying to show progress from something in the module? I'd also ask why a module, but that's not really relevant to the problem at hand.
    The only reason why I am calling it from Module1 is because I don't want all of the code to be in Form1.

    Basically Form1 has all of the main code and when necessary it makes calls to the subs/functions in Modules. I have one global backgroundworker to which everything is reporting.

  10. #10
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Background Worker not Reporting Progress

    Like I said, I didn't want to get into it....

    But my other point still stands... there's no guarantee that your form is actually the default instance... so your module calling into it could be calling into a different instance of the form... which is why you're not seeing the status being reported.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  11. #11

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker not Reporting Progress

    I understand the part that I am not calling the proper instance of the form.
    What I don't know is how to actually call the proper form.
    Grimfort wrote earlier that I should do something like this:
    Friend TheMainForm As Main << inside a module or something
    Sub FormLoad
    TheMainForm = Me
    End Sub
    But I don't know how to apply this to the code I posted above...
    I think I will have to find some other way to report to the main form. Hmm...

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

    Re: Background Worker & Progress (reporting to the default instance of the main form)

    When you select a startup form in a VB.NET app, it is created by the application framework automatically and it IS the default instance of its type. Your problem is that you are trying to refer to the default instance of Form1 in a method that is NOT executed on the UI thread. As I explain in my blog post, default instances are thread-specific, so that actually creates a new Form1 instance.

    If you wanted to keep going down that road then what you could is, instead of using the default instance of Form1 in your module, you could use My.Application.ApplicationContext.MainForm to access the startup form.

    That's only going to work for the startup form though. It would be better if you did it the "proper" way. In the DoWork event handler, like every event handler, there is a 'sender' parameter. That refers to the object that raised the event, i.e. the BackgroundWorker object. You can then pass that object to any method that needs to report progress and that method can access the BackgroundWorker directly, without caring if and what form it's on. Your code for Form1 then becomes:
    Code:
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Dim worker = DirectCast(sender, System.ComponentModel.BackgroundWorker)
    
            showTest(worker)
            Module1.showTestFromModule1(worker)
        End Sub
    
        Private Sub showTest(worker As System.ComponentModel.BackgroundWorker)
            worker.ReportProgress(0, "This shows on the main form.")
        End Sub
    
        Private Sub progress(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            Dim message As String = CStr(e.UserState)
            TextBox1.AppendText(message & vbCrLf)
        End Sub
    
    End Class
    and the module becomes:
    Code:
    Module Module1
    
        Public Sub showTestFromModule1(worker As System.ComponentModel.BackgroundWorker)
            worker.ReportProgress(0, "This doesn't show up on the main form.")
        End Sub
    
    End Module
    You don't actually need to do it within the form itself, given that that is already working as is, but I've done it there for consistency.
    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

  13. #13

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker & Progress (reporting to the default instance of the main form)

    Quote Originally Posted by jmcilhinney View Post
    (...)You don't actually need to do it within the form itself, given that that is already working as is, but I've done it there for consistency.
    Thank you so much for your explanation. This makes so much more sense now.

  14. #14
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: Background Worker not Reporting Progress

    Quote Originally Posted by marcellus View Post
    The only reason why I am calling it from Module1 is because I don't want all of the code to be in Form1.
    There is no reason a form cannot contain all your code. You could use a Partial class to move the code into another file, but there is no real benefit.

  15. #15

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker not Reporting Progress

    Quote Originally Posted by Grimfort View Post
    There is no reason a form cannot contain all your code. You could use a Partial class to move the code into another file, but there is no real benefit.
    That's it. All this time I was making a simple problem much more complicated.
    At least I learned more about instances in vb. Maybe in the future I will actually use it and now I will convert my project to use Partial Classes. Gasp...

    I feel dumb...

    Thank you all for your help!

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

    Re: Background Worker & Progress (reporting to the default instance of the main form)

    It's not necessarily a bad thing to try to move code out of a form. Ideally, forms should deal with presentation and nothing else, so likely this background task actually does belong outside. That said, what you would normally do is define a class that was responsible for this task. You would create an instance and then tell it to do its job. That instance could then raise an event to indicate a change in progress and your form would handle that event and then update the UI accordingly. As you can see, the form handles the presentation aspect without doing the actual work. You could still use an event with a module if you wanted to.
    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

  17. #17

    Thread Starter
    Junior Member
    Join Date
    Sep 2011
    Posts
    27

    Re: Background Worker & Progress (reporting to the default instance of the main form)

    Quote Originally Posted by jmcilhinney View Post
    It's not necessarily a bad thing to try to move code out of a form. Ideally, forms should deal with presentation and nothing else, so likely this background task actually does belong outside. That said, what you would normally do is define a class that was responsible for this task. You would create an instance and then tell it to do its job. That instance could then raise an event to indicate a change in progress and your form would handle that event and then update the UI accordingly. As you can see, the form handles the presentation aspect without doing the actual work. You could still use an event with a module if you wanted to.
    I see. I think I will apply it in my project after all. Coming from a console only apps, dealing with UI is all new to me. Everyday something new!

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