|
-
May 23rd, 2012, 10:09 AM
#1
Thread Starter
Junior Member
[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.
-
May 23rd, 2012, 10:28 AM
#2
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)?
-
May 23rd, 2012, 10:37 AM
#3
Thread Starter
Junior Member
Re: Background Worker not Reporting Progress
 Originally Posted by Grimfort
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!!
-
May 23rd, 2012, 10:53 AM
#4
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.
-
May 23rd, 2012, 10:57 AM
#5
Thread Starter
Junior Member
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?
-
May 23rd, 2012, 11:37 AM
#6
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
-
Jun 8th, 2012, 02:58 PM
#7
Thread Starter
Junior Member
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
-
Jun 8th, 2012, 03:17 PM
#8
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
-
Jun 8th, 2012, 03:21 PM
#9
Thread Starter
Junior Member
Re: Background Worker not Reporting Progress
 Originally Posted by techgnome
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.
-
Jun 8th, 2012, 03:34 PM
#10
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
-
Jun 8th, 2012, 04:07 PM
#11
Thread Starter
Junior Member
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...
-
Jun 9th, 2012, 01:19 AM
#12
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.
-
Jun 9th, 2012, 07:52 AM
#13
Thread Starter
Junior Member
Re: Background Worker & Progress (reporting to the default instance of the main form)
 Originally Posted by jmcilhinney
(...)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.
-
Jun 9th, 2012, 02:33 PM
#14
Re: Background Worker not Reporting Progress
 Originally Posted by marcellus
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.
-
Jun 11th, 2012, 10:20 AM
#15
Thread Starter
Junior Member
Re: Background Worker not Reporting Progress
 Originally Posted by Grimfort
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!
-
Jun 11th, 2012, 10:43 AM
#16
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.
-
Jun 11th, 2012, 11:02 AM
#17
Thread Starter
Junior Member
Re: Background Worker & Progress (reporting to the default instance of the main form)
 Originally Posted by jmcilhinney
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|