Results 1 to 21 of 21

Thread: Wait for Backgroundworker to finish

  1. #1

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Wait for Backgroundworker to finish

    How can I wait for a backgroundWorker to finish and still be in the same void?
    For example:

    I send a list with files to process to a void, DoThem(list).
    Then in that void, if the file is a txt, send it to backgroundworker1. If the file is a jpg send it to backgroundworker2.

    But I only want one backgroundworker to run at the same time (reporting progress to the same progressbar).

    I know the bw has a bwFinished event, but if I need to use that I would need to do a hell of a more programming that looks quite ugly to me (passing a parameter with what to do when finished blablabla).

    What I have read you can use the WaitOne thingy. But it locks the UI and I want to be able to change the progressbar all the time.
    Last edited by Cyb3rH4Xter; Mar 20th, 2011 at 05:12 AM.

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

    Re: Wait for Backgroundworker to finish

    There's no such thing as "a void". It's a function, with a return type of void, i.e. it doesn't return anything at all.

    What's the point of using a BackgroundWorker at all if you're going to wait for it to finish? You may as well just do the work right there in the same function. The point of using the BackgroundWorker is that the UI remains responsive because the UI thread is free while the work is done in the DoWork event handler. If the UI thread is waiting for the background work to finish then it's not free, so the UI doesn't remain responsive.

    You can't have your cake and eat it too. Either the UI thread is free or it's not. You can't make the UI thread wait but still have it free. The BackgroundWorker has been made to work in a paraticular way. That's how it works and that's how you use it. Anything that you want to do specifically when the BackgroundWorker finishes you do in the RunWorkerCompleted event handler. That's what it's for and that's how you use it. It's proper programming. If you really feel that you need to do a hell of a lot more programming then you're not doing it right.
    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

  3. #3

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    Well thank you for taking time to answer, great post.

  4. #4
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: Wait for Backgroundworker to finish

    I think the point was to show a progress bar.

    I'm doing something similar for a project I'm tinkering on and I'll paste some relevant bits. I don't use the background worker, I just use the regular threading.

    Here's how it does - I choose a file (I'm reading LWO files) and then this whole process starts. It not only updates a progress bar, but it also displays status messages. Code for this functionality:

    In the FORM code, I call the following functions in my custom class:
    Code:
    		System.Threading.Thread WorkMule = null;
    		public void SetWorkingFile(string File)
    		{
    			FileName = File;
    			Reader = new LwoFormatReader();
    			Reader.FileName = FileName;
    			WorkMule = new System.Threading.Thread(new System.Threading.ThreadStart(Reader.DoWork));
    		}
    
    		public void BeginWork()
    		{
    			pbLoad.Value = 100;
    			if(WorkMule != null)
    			{
    				WorkMule.Start();
    			}
    		}
    That's what starts the processing. Here's some of what the LwoFormatReader looks like:

    Code:
    			protected internal string FileName { get; set; }
    
    			private object ProgressLock = new object();
    			private object MessageLock = new object();
    			private int _BytesRead = 0;
    			private int _FileSize = 0;
    
    
    			private List<string> _Messages = new List<string>();
    
    //other stuff
    
    protected internal string Messages
    			{
    				get
    				{
    					lock(MessageLock)
    					{
    						int Start = Math.Max(0, _Messages.Count - 20);
    						int End = _Messages.Count - Start;
    						return string.Join("\r\n", _Messages.GetRange(Start, End).ToArray());
    					}
    				}
    
    				set
    				{
    					lock(MessageLock)
    					{
    						//if(_Messages.Count > 80)
    						//    _Messages.RemoveAt(0);
    						_Messages.Add(value);
    					}
    				}
    			}
    
    			protected internal int Progress
    			{
    				get
    				{
    					lock(ProgressLock)
    					{
    						if(_FileSize == 0)
    						{
    							return 0;
    						}
    
    						return (int)(((double)BytesRead / (double)_FileSize) * 100);
    					}
    
    				}
    			}
    			protected internal int BytesRead
    			{
    				get
    				{
    					lock(ProgressLock)
    					{
    						return _BytesRead;
    					}
    				}
    
    				set
    				{
    					lock(ProgressLock)
    					{
    						_BytesRead = value;
    					}
    				}
    			}
    
    			protected internal int FileSize
    			{
    				get
    				{
    					lock(ProgressLock)
    					{
    						return _FileSize;
    					}
    				}
    
    				set
    				{
    					lock(ProgressLock)
    					{
    						_FileSize = value;
    					}
    				}
    			}
    
    
    			protected internal enum WorkStatus
    			{
    				NotStarted,
    				LoadingFile,
    				ReadingHeader,
    				ReadingChunk,
    				ReadingImages,
    				ReadingPoints,
    				ReadingPolys,
    				ReadingSurfaces,
    				ReadingTags,
    				ReadingUnknown,
    				ReadingVertices,
    				Loaded,
    				Error
    			}
    
    			private WorkStatus Status = WorkStatus.NotStarted;
    			private object StatusLock = new object();
    
    			protected internal WorkStatus GetStatus()
    			{
    				WorkStatus RetStatus = WorkStatus.NotStarted;
    				lock(StatusLock)
    				{
    					RetStatus = Status;
    				}
    
    				return RetStatus;
    			}
    
    			private void SetStatus(WorkStatus _Status)
    			{
    				lock(StatusLock)
    				{
    					Status = _Status;
    				}
    			}
    
    			protected internal string GetAllMessages()
    			{
    				return String.Join("\r\n", _Messages.ToArray());
    			}
    
    			protected internal string GetStringStatus()
    			{
    				switch(GetStatus())
    				{
    					case WorkStatus.Loaded:
    						return "Loaded";
    					case WorkStatus.LoadingFile:
    						return "Loading File";
    					case WorkStatus.NotStarted:
    						return "Waiting On Work";
    					case WorkStatus.ReadingChunk:
    						return "Reading Chunk Data";
    					case WorkStatus.ReadingHeader:
    						return "Reading Header";
    					case WorkStatus.ReadingImages:
    						return "Reading Image-based Data";
    					case WorkStatus.ReadingPoints:
    						return "Reading Point List";
    					case WorkStatus.ReadingPolys:
    						return "Reading Polygons";
    					case WorkStatus.ReadingSurfaces:
    						return "Reading Surfaces";
    					case WorkStatus.ReadingTags:
    						return "Reading Tags";
    					case WorkStatus.ReadingUnknown:
    						return "Reading Unknown Chunk";
    					case WorkStatus.ReadingVertices:
    						return "Reading Vertices";
    					case WorkStatus.Error:
    						return "An error has occurred";
    					default:
    						return "Status Error";
    				}
    			}
    This lets me add messages by doing .Messages = "something" and they're appended. But it also lets me read the messages. The key here are the lock objects - they ensure that even though I'm about to access these on different threads (one for UI and one for processing) I don't run in to a thread unsafe operation.

    As work is done in the reader, it does the following: (this is just one example)

    Code:
    //Inside a switch where I'm checking for different file sections I have:
    							case "tags":
    								SetStatus(WorkStatus.ReadingTags);
    								int TagsKnown = Tags.Count;
    								GetTags(ChunkBytes, Chunk.Size);
    								int TagsNow = Tags.Count;
    								BytesRead += Chunk.Size;
    								for(int i = TagsKnown ; i < TagsNow ; i++)
    								{
    									Messages = string.Format("\t{0}\tTag Found: {1}", i.ToString(), Tags[i]);
    								}
    								break;
    The FORM has a timer on it. Here's the "tick" code. (I set the interval to 100ms and it's already turned on)

    Code:
    		private void tStatus_Tick(object sender, EventArgs e)
    		{
    			if(Reader != null && bRead == true) 
    			{
    				lblInfo.Text = Reader.GetStringStatus();
    				txtMessages.Text = Reader.Messages;
    				pbLoad.Value = Math.Min(Reader.Progress, 100); //Progress Bar
    
    				if(Reader.GetStatus() == LwoFormatReader.WorkStatus.Error ||
    					Reader.GetStatus() == LwoFormatReader.WorkStatus.Loaded)
    				{
    					txtMessages.Text = Reader.GetAllMessages();
    					txtMessages.ScrollBars = ScrollBars.Vertical;
    					txtMessages.SelectionStart = txtMessages.Text.Length - 1;
    					txtMessages.ScrollToCaret();
    					bRead = false;
    					//Other work
    					tStatus.Enabled = false;
    				}
    			}
    So there's an example from real-world usage.
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

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

    Re: Wait for Backgroundworker to finish

    If the issue is indeed displaying progress then any reading about the BackgroundWorker will reveal that it has several members related to just that: the WorkerReportsProgress property, the ReportProgress method and the ProgressChanged event. There are many examples around of their use, including one that I posted on this site in the VB.NET CodeBank forum.
    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
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Wait for Backgroundworker to finish

    I think you've both missed the actual question being asked

    Quote Originally Posted by Cyb3rH4Xter View Post
    I send a list with files to process to a void, DoThem(list).
    Then in that void, if the file is a txt, send it to backgroundworker1. If the file is a jpg send it to backgroundworker2.

    But I only want one backgroundworker to run at the same time (reporting progress to the same progressbar).
    There are two background workers, but only one should be processing at any one time.

    The answer, of course, is to have just one background worker, that processes both sorts of files.

    I'm not sure what you mean by "sending" the files to the background worker. I would simply have the backgroundworker process the list. It sounds like you may be doing something a little strange, so if it isn't clear how to use a single backgroundworker, you may want to post your code so we can see if you're using it correctly.

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

    Re: Wait for Backgroundworker to finish

    Quote Originally Posted by Evil_Giraffe View Post
    I think you've both missed the actual question being asked
    I think you may be right. In that case, the OP has things the wrong way around. Rather than one method to process the list and then two BackgroundWorkers to process individual files, it should be one BackgroundWorker to process the list and then two methods to process individual files. The DoWork event handler contains a For Each loop to process the list and an If or Select Case statement to decide which file-processing method to call.
    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

  8. #8

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    Evil Giraffe is right. And the answer by both of you are exactly what I was looking for and considered as the best alternative this morning. By sending I meant like set it as the argument and start bw1 and so on.

    But before I start I then have one question: if I call a method in a bw it will be executed in the bw, right?

    Then I will just need to do something like this:

    Code:
    bw_DoWork(...)
    
    If File is jpg then
    
    RunJPG(file)
    
    Else If file is txt then
    
    RunTXT(file)
    
    End If
    Oops, vb code, but hey, I used it as a "language", not "programming language" at the moment

  9. #9
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: Wait for Backgroundworker to finish

    Quote Originally Posted by Cyb3rH4Xter View Post
    Evil Giraffe is right. And the answer by both of you are exactly what I was looking for and considered as the best alternative this morning. By sending I meant like set it as the argument and start bw1 and so on.

    But before I start I then have one question: if I call a method in a bw it will be executed in the bw, right?

    Then I will just need to do something like this:

    Code:
    bw_DoWork(...)
    
    If File is jpg then
    
    RunJPG(file)
    
    Else If file is txt then
    
    RunTXT(file)
    
    End If
    Oops, vb code, but hey, I used it as a "language", not "programming language" at the moment
    It'll be executed on the same thread that called it.

    Set up your code like this:

    Code:
    MyWorkerClass ObjectName = new MyWorkerClass();
    ObjectName.Data = Data; //IE Send it everything it needs in order to work
    ObjectName.WorkType = MyWorkerClass.WorkTypes.Jpeg; //Or .Text - see below
    WorkMule = new System.Threading.Thread(ObjectName.DoWork);
    
    //Futher down, in the MyWorkerClass class
    public enum WorkTypes{
       Jpeg,
       Text
    }
    
    public WorkTypes WorkType { get; set; }
    
    public void DoWork(){
       switch(WorkType){
          case WorkTypes.Jpeg:
             FunctionToProcessJpeg();
             break;
          case WorkTypes.Text:
             FunctionToProcessText();
             break;
       }
    }
    This is all written on the fly - if there's an error I'm sure you'll be able to fix it right up with the help of the compiler, but this should give you the right idea of how to go about this.
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

  10. #10

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    I see thank you for the code. Though there is one problem, how do I report the progress from those Functions?

    For example in the function FunctionToProcessText I want it to report progress as it goes through the text, but how is that possible?

    This is just an example as you know, in my code I am processing videofiles.

  11. #11
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: Wait for Backgroundworker to finish

    My answer would be to review the first set of code that I pasted above.

    That said, jmc mentioned that there's an intrinsic property to the background worker - I'm sure if you googled that, you'd find it lickety split.
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

  12. #12

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    I took a look again at your code, figured that out with the timer before I wrote, but just wanted to know if there were a better method.

    But I don't understand what you meant with the second line, my English is good but not the best
    I understand that it is about a property that jmc mentioned, but I couldn't find that and don't really know what to google.

    But yeah basically I know what to do, so thank you for your help, now I can continue my work.

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

    Re: Wait for Backgroundworker to finish

    Quote Originally Posted by Cyb3rH4Xter View Post
    I understand that it is about a property that jmc mentioned, but I couldn't find that and don't really know what to google.
    Don't Google. Read the documentation.
    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

  14. #14
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: Wait for Backgroundworker to finish

    Google usually leads to not only the documentation, but additional sites with examples. =)

    Regardless, I think he's on his way. Woot for that.
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

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

    Re: Wait for Backgroundworker to finish

    Quote Originally Posted by Lord_Rat View Post
    Google usually leads to not only the documentation, but additional sites with examples. =)

    Regardless, I think he's on his way. Woot for that.
    The documentation always leads to the documentation. You can then search elsewhere for additional examples if required. I'm not suggesting that sources other than the documentation should be used. I'm stating that the documentation should always be the first source used, assuming that you know what type and/or member you need to read the documentation for. In this case, that type is the BackgroundWorker. How to report progress would have been obvious in that case. Other sources may well then not have been needed at all. I speak from my own experience, so I know that it's so.
    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

  16. #16
    C# Aficionado Lord_Rat's Avatar
    Join Date
    Sep 2001
    Location
    Cave
    Posts
    2,497

    Re: Wait for Backgroundworker to finish

    Quote Originally Posted by jmcilhinney View Post
    I speak from my own experience, so I know that it's so.
    Same. =)

    And I'm explaining my answer, not contradicting yours.
    Need to re-register ASP.NET?
    C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i

    (Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)

  17. #17

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    Thank you for both of your answers, will try to find what you mean.

    EDIT:

    Wow I feel quite dumb. Reporting the progress isn't hard, just calling bw.ReportProgress works from withing the function. But what I don't understand is how I am supposed to set the e.Result and the e.Cancel. Or have you already answered to that? :S
    What I know you can't access those from anywhere.
    Last edited by Cyb3rH4Xter; Mar 24th, 2011 at 05:25 PM.

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

    Re: Wait for Backgroundworker to finish

    Yes I have already answered that. I've pointed you to the CodeBank thread of mine dedicated to the BackgroundWorker and it has code examples that demonstrate both those properties.
    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

  19. #19

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    Oh didn't see that point but checked you submission in the codebank but it didn't say anything about setting the Result and Cancel property in for example a function run from the backgroundworker?

    One way I could make it is that I do the checking in the function and if the user cancels, I cancel and return like 0 back to the DoWork and then the DoWork sets the rest.

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

    Re: Wait for Backgroundworker to finish

    This situation is no different to many, many others that you've encountered before. The DoWork event handler is a method, just like any other method. In that method, you have an object and you want to set a property of that object based on what happens in another method. How would you usually do that? There are only two ways:

    1. Pass the object to the other method and let it set the property.
    2. Get a result from the other method and set the property based on that.

    That is how programming works. It's irrelevant that you're using a BackgroundWorker and this is originating from the DoWork event handler. Methods are methods, objects are objects and properties are properties. Those would be your two choices in any method, even if there was no multi-threading at all.
    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

  21. #21

    Thread Starter
    Hyperactive Member Cyb3rH4Xter's Avatar
    Join Date
    May 2009
    Location
    Sweden
    Posts
    449

    Re: Wait for Backgroundworker to finish

    Okay thank you. Problem Solved.

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