|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
c# newbie needs help with backgroundworkerI have a form which temporarily creates another form and has a progressbar on it. I got trouble with updating the screen, if I didn't use a background-worker. Therefore: My code looks something like the following: public partial class newForm : Form { public newForm() { InitializeComponent(); //this.Show(); //this.Activate(); this.progressBar1.Step = 1; this.progressBar1.Maximum = 100; BackgroundWorker bw0 = new BackgroundWorker(); bw0.WorkerReportsProgress = true; bw0.DoWork += delegate(object sender0, DoWorkEventArgs e0) { for (int i = 0; i < 15; i++) { System.Threading.Thread.Sleep(50); bw0.ReportProgress(i); } }; bw0.ProgressChanged += delegate(object sender0, ProgressChangedEventArgs e0) { this.progress_indicator.Text = string.Format("{0}%", e0.ProgressPercentage); this.progressBar1.PerformStep(); }; bw0.RunWorkerCompleted += delegate(object sender0, RunWorkerCompletedEventArgs e0) { // Here I insert 6 extra background-workers after the previous completed - this is wrong! } Okay: My problem is that when I put code inside bwXXXX.RunWorkerCompleted, everything works - except that I cannot continue to update by using my bwXXXXX.ReportProgress(i). Therefore I have some really really ugly code with many layers of background- workers... In addition, I need to get something like: (int)this.Handle I cannot seem to be able to get: (int)this.Handle inside any of my bwXXXXX.DoWork'ers.... Instead of having all my background-workers, I only need a single one and put my code inside the bw0.DoWork (my code is 100% sequential). Any hints on why this doesn't work - do I need to post more code? I hope this is sufficient for a qualified answer... On Thu, 11 Jun 2009 05:07:43 -0700, c-sharp newbie! <newsbo***@gmail.com>
wrote: Show quoteHide quote > [...] What does "I cannot continue to update by using my > bw0.RunWorkerCompleted += delegate(object sender0, > RunWorkerCompletedEventArgs e0) > { > // Here I insert 6 extra background-workers after > the previous completed - this is wrong! > } > > > Okay: My problem is that when I put code inside > bwXXXX.RunWorkerCompleted, everything works - except that I cannot > continue to update by using my bwXXXXX.ReportProgress(i). Therefore I > have some really really ugly code with many layers of background- > workers... byXXXXX.ReportProgress(i)" mean? Why, when the problem you're having is apparently related to the code you put into the RunWorkerCompleted event handler, is that the one event handler that you failed to actually show the code for? > In addition, I need to get something like: (int)this.Handle Suggestion: instead of casting the Handle value, use the ToInt32() method > > I cannot seem to be able to get: (int)this.Handle inside any of my > bwXXXXX.DoWork'ers.... Instead of having all my background-workers, I > only need a single one and put my code inside the bw0.DoWork (my code > is 100% sequential). on it. As for the specific concern, there's nothing in the code you posted that demonstrates how you're trying to "get: (int) this.Handle", never mind what mind be going wrong with such code. Assuming your DoWork event handlers are methods within your Form sub-class, "this.Handle" should be a valid expression, and it should evaluate to some specific value at run-time. > Any hints on why this doesn't work - do I need to post more code? I Unfortunately, it's not. See above for specific things that are missing > hope this is sufficient for a qualified answer... from the code, and keep in mind that a _complete_ code example is almost always the best. There's no way for anyone to actually compile and run the code you posted without extra work, including some guesswork. In any case, if you don't post any of the code that is actually giving you problems, it's impossible for anyone to provide any useful comments about that code. Pete
Show quote
Hide quote
On 11 Jun., 19:17, "Peter Duniho" <NpOeStPe***@nnowslpianmk.com> Ok, it means: I cannot continue to update my GUI as I could use in thewrote: > On Thu, 11 Jun 2009 05:07:43 -0700, c-sharp newbie! <newsbo***@gmail.com> > wrote: > > > [...] > > bw0.RunWorkerCompleted += delegate(object sender0, > > RunWorkerCompletedEventArgs e0) > > { > > // Here I insert 6 extra background-workers after > > the previous completed - this is wrong! > > } > > > Okay: My problem is that when I put code inside > > bwXXXX.RunWorkerCompleted, everything works - except that I cannot > > continue to update by using my bwXXXXX.ReportProgress(i). Therefore I > > have some really really ugly code with many layers of background- > > workers... > > What does "I cannot continue to update by using my > byXXXXX.ReportProgress(i)" mean? bw0.DoWork-function. If I try to update my GUI in the bw0.RunWorkerCompleted-function, it fails. That's what it means... I then found the explanation, that there are separate threads. I need to pass information from the GUI-thread to the worker-thread - that's my problem. I don't know how to do this. > Why, when the problem you're having is I'm using an API which I don't think any of you have. The API requires> apparently related to the code you put into the RunWorkerCompleted event > handler, is that the one event handler that you failed to actually show > the code for? that I pass (int)this.Handle, to the API-function I want to use. Therefore I only need how to pass the value of (int) this.Handle (from the GUI-thread) to the worker thread. At least, that is what I think... > > In addition, I need to get something like: (int)this.Handle Okay, but still. I guess I don't complety understand the concept of> > > I cannot seem to be able to get: (int)this.Handle inside any of my > > bwXXXXX.DoWork'ers.... Instead of having all my background-workers, I > > only need a single one and put my code inside the bw0.DoWork (my code > > is 100% sequential). > > Suggestion: instead of casting the Handle value, use the ToInt32() method > on it. this.handle... Any help or comments on "this.handle" in relation to the two threads in background-worker (GUI- vs. worker-thread) would be appreciated... > As for the specific concern, there's nothing in the code you posted that Here's what I try to do:> demonstrates how you're trying to "get: (int) this.Handle", never mind > what mind be going wrong with such code. Assuming your DoWork event > handlers are methods within your Form sub-class, "this.Handle" should be a > valid expression, and it should evaluate to some specific value at > run-time. ------------ CODE THAT DOESN'T WORK:------------ bw0.DoWork += delegate(object sender0, DoWorkEventArgs e0) { for (int i = 0; i < 5; i++) { System.Threading.Thread.Sleep(50); bw0.ReportProgress(i); } int test = (int)this.Handle; //// DOESN'T WORK: "NOT IN THE GUI-THREAD" MessageBox.Show("integer = " + Convert.ToString (test)); for (int i = 5; i < 15; i++) { System.Threading.Thread.Sleep(50); bw0.ReportProgress(i); } // do something more.... }; ------------ CODE THAT WORKS:------------ bw0.RunWorkerCompleted += delegate(object sender0, RunWorkerCompletedEventArgs e0) { int test = (int)this.Handle; //// WORKS BECAUSE WE'RE IN THE GUI-THREAD MessageBox.Show("integer = " + Convert.ToString (test)); // however: This doesn't work: for (int i = 0; i < 5; i++) { System.Threading.Thread.Sleep(50); bw0.ReportProgress(i); // New non-gui "worker- thread", therefore this fails } > > Any hints on why this doesn't work - do I need to post more code? I I cannot post complete code, because I'm using some API which I guess> > hope this is sufficient for a qualified answer... > > Unfortunately, it's not. See above for specific things that are missing > from the code, and keep in mind that a _complete_ code example is almost > always the best. There's no way for anyone to actually compile and run you don't have. And my question should be so general, that it suffices (I hope). > the code you posted without extra work, including some guesswork. In any I think I described my problem, however in a newbie-way and that might> case, if you don't post any of the code that is actually giving you > problems, it's impossible for anyone to provide any useful comments about > that code. not be good enough. Now I believe I've showed it. On Fri, 12 Jun 2009 08:01:43 -0700, c++ newbie! <newsbo***@gmail.com>
wrote: > [...] The most straightforward way is to use the RunWorkerAsync() overload that > I need to pass information from the GUI-thread to the worker-thread - > that's my problem. I don't know how to do this. allows you to pass an argument to your DoWork event handler (the argument value can be retrieved from the DoWorkEventArgs object passed to the handler). Alternative methods include: -- Copying the value of the Handle property to a private class member field, and then reading it from there. The problem isn't with the value, it's with the Handle property itself. -- Accessing the property using Control.Invoke() on an anonymous method that gets the property value and returns it. Invoked methods can return values to the caller, even when using Control.Invoke(). One thing that still bugs me about your code example is that the "CODE THAT DOESN"T WORK" and the "CODE THAT WORKS" looks basically the same. The only significant difference is that in one case you are handling the DoWork event, and in the other case you are handling the RunWorkerCompleted event. But, those events are for completely different purposes. It doesn't make sense that you could treat the events interchangeably. In particular, while you may be able to resolve the business of retrieving the Handle property value in the worker thread, whether you can safely use that value anywhere else is still open to question. Likewise, putting code in the RunWorkerCompleted event handler that does the same thing as the code in your DoWork event handler begs the question: what's the point of the background worker thread at all, if you are satisfied executing the exact same code on the main GUI thread? Anyway, hopefully the information above helps you solve your problem. Pete On 12 Jun., 19:30, "Peter Duniho" <NpOeStPe***@nnowslpianmk.com> Aah, thank you very much! This seem to work on a minimal example herewrote: > On Fri, 12 Jun 2009 08:01:43 -0700, c++ newbie! <newsbo***@gmail.com> > wrote: > > > [...] > > I need to pass information from the GUI-thread to the worker-thread - > > that's my problem. I don't know how to do this. > > The most straightforward way is to use the RunWorkerAsync() overload that > allows you to pass an argument to your DoWork event handler (the argument > value can be retrieved from the DoWorkEventArgs object passed to the > handler). at home :-) However, I have to check it for real on monday/tuesday on my real code and cross my fingers that everything works out :-) > Alternative methods include: What you're telling me, is a true eye-opener. I value that, however> > -- Copying the value of the Handle property to a private class member > field, and then reading it from there. The problem isn't with the value, > it's with the Handle property itself. what do you mean with the last sentence? I think I understand the alternative method, but not the problem... > -- Accessing the property using Control.Invoke() on an anonymous Thanks: Finally, I got something to work and began understanding Invoke> method that gets the property value and returns it. Invoked methods can > return values to the caller, even when using Control.Invoke(). () a bit. This page helped a lot: http://msdn.microsoft.com/en-us/library/ms171728.aspx I now have something like this: delegate int getHandleCallback(); // I haven't really understood this yet private int getHandle() { return (int)this.Handle; } And in my doworker-method: int val; getHandleCallback GH = new getHandleCallback(getHandle); object valO = this.Invoke(GH); val = (int)valO; //val = (int)this.Handle; // produces some thread error/ casts exception MessageBox.Show("Value is (from this.Invoke): " + val.ToString()); > One thing that still bugs me about your code example is that the "CODE Yes, because I don't want my code in the "worker-completed UI"-thread,> THAT DOESN"T WORK" and the "CODE THAT WORKS" looks basically the same. but in the worker-thread and I got exceptions when I tried to move my code into the worker-thread. So I don't understand exactly, what's bugging you other than I couldn't make it work before (I haven't tested it on my whole code, I just ran a minimal example here at home which I believe has shown that your suggestions really have helped me)? > The only significant difference is that in one case you are handling the When you're a noob like me, you just put the code whereever it works> DoWork event, and in the other case you are handling the > RunWorkerCompleted event. But, those events are for completely different > purposes. It doesn't make sense that you could treat the events > interchangeably. out. When you're trying to learn to improve your code like me, I ask for help because I want all "work-stuff" in the worker-thread instead of the completed-thread. My real problem is that I have multiple embedded background-workers in the run-completed method, instead of putting all inside one single background-worker "do-work"-method. By following your suggestions I improve my code a lot, make it easier to look at and doesn't need multiple background-workers due to the requirement for knowing things from the main (UI)-thread. I'm not sure if I removed your concerns? > In particular, while you may be able to resolve the business of retrieving Yes, I agree: Whether I can use it anywhere else is still a question I> the Handle property value in the worker thread, whether you can safely use > that value anywhere else is still open to question. Likewise, putting have to check tomorrow... I hope - or else I guess I must learn more about invoke... I guess by using invoke, is the way to do it properly, if I get problems... > code in the RunWorkerCompleted event handler that does the same thing as The point is that if you don't use a BW, the form-window is "locked"> the code in your DoWork event handler begs the question: what's the point > of the background worker thread at all, if you are satisfied executing the > exact same code on the main GUI thread? while you're running your code. You don't see any progress indication and my labels don't get updated, so the user can't see what's happening. Therefore you need a background-worker. And so far most of my code was ran in the "completed"-event because that was the only place I could make it work. This introduced the need for multiple background-workers, because I have multiple tasks I want to solve while the user can see the program progress. > Anyway, hopefully the information above helps you solve your problem. Yes, it was very helpful and thank you. I still need to check ittomorrow/tuesday I hope on my full code. My test code here at home shows me that your suggestions was very valuable and I learned something from them. If this is sequential work (my understanding is that you want a single
background thread at any one time ?) , you could put all in DoWork and use a single Backgroundworker ? Another option would be to update the DoWork delegate and then use the bsame backgrounder again... From the code I see I'm not sure what you are trying to do (dowork currently just updates the progress, it should be used to perform the actual work (in additioon to updateing the progress). Not related but as a side note putting the thread to sleep shouldn' t be needed. The problme you have here is that if you call the UI thread too frequently you kill the benefit of using a background thread. My pattern here is to report progress if progress really changed (but this is unrelated -- Patrice "c-sharp newbie!" <newsbo***@gmail.com> a écrit dans le message de groupe de 5d4a0546-aeb2-4313-9f1a-f4644af83***@21g2000vbk.googlegroups.com...discussion : Show quoteHide quote > Dear all, > > I have a form which temporarily creates another form and has a > progressbar on it. I got trouble with updating the screen, if I didn't > use a background-worker. Therefore: My code looks something like the > following: > > public partial class newForm : Form > { > public newForm() > { > InitializeComponent(); > > //this.Show(); > //this.Activate(); > this.progressBar1.Step = 1; > this.progressBar1.Maximum = 100; > > BackgroundWorker bw0 = new BackgroundWorker(); > bw0.WorkerReportsProgress = true; > > bw0.DoWork += delegate(object sender0, DoWorkEventArgs e0) > { > for (int i = 0; i < 15; i++) > { > System.Threading.Thread.Sleep(50); > bw0.ReportProgress(i); > } > }; > bw0.ProgressChanged += delegate(object sender0, > ProgressChangedEventArgs e0) > { > this.progress_indicator.Text = string.Format("{0}%", > e0.ProgressPercentage); > this.progressBar1.PerformStep(); > }; > bw0.RunWorkerCompleted += delegate(object sender0, > RunWorkerCompletedEventArgs e0) > { > // Here I insert 6 extra background-workers after > the previous completed - this is wrong! > } > > > Okay: My problem is that when I put code inside > bwXXXX.RunWorkerCompleted, everything works - except that I cannot > continue to update by using my bwXXXXX.ReportProgress(i). Therefore I > have some really really ugly code with many layers of background- > workers... > > In addition, I need to get something like: (int)this.Handle > > I cannot seem to be able to get: (int)this.Handle inside any of my > bwXXXXX.DoWork'ers.... Instead of having all my background-workers, I > only need a single one and put my code inside the bw0.DoWork (my code > is 100% sequential). > > Any hints on why this doesn't work - do I need to post more code? I > hope this is sufficient for a qualified answer...
ShortWay in C# conversion from C++ to C#
Why there are two diffrent result in two almost same formula code access security Weird behavior of ListView.ShowGroups property A Radius Search? No Implicit Conversion For Strongly Typed DataSet In VS2005 Website Problems - Outlook Express N/A Greek letters with subscripts/superscripts extending existing application Memory used in unmanaged space |
|||||||||||||||||||||||