Windows Develop Bookmark and Share   
 index > Windows Forms General > Windows Forms TextBox updating Text field.
 

Windows Forms TextBox updating Text field.

I have Windows.Forms application I am building. I have a long, complex step which must FTP a series of files to local storage and then translate the files etc.

I added a TextBox field to my form with the intention of writing a series of running status messages to it to keep the user informedof its progress. I am attempting to write messages to it as the process runs through its steps. I write to the Text box using:
private void statMsg(string msg)
    {
      statusBox.Text = string.Copy(msg);
      statusBox.Invalidate();
    }
However, only the first and the last message are displayed in the TextBox - nothing in between while the file transfers are happening. I've tried inserting TextBox1.Invalidate() and TextBox1.Refresh() calls in the code, but nothing seems to cause the status messages to be displayed there. Is there something I'm missing which relinquishes control to the Form code to cause it to redraw objects that are pending a re-paint?

Thanks in advance for any tips you might be able to toss my way.
Code Lizard  Monday, September 28, 2009 8:18 PM
Hi Code Lizard,

I am writing to check if you have made any progress on solving the issue. I quite agree with using multi-thread in this application. And also I think you can give Application.DoEvent a try. Here is the information about that method.
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx

If you have any problems, please feel free to tell us. If you can post more code, it will help us to understand the case clearly.

Sincerely,
Kira Qian
Send us any feedback you have about the help from MSFT at fbmsdn@microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework!
Kira Qian  Wednesday, September 30, 2009 3:59 AM
Refresh won't work alone. Application.DoEvents() would (combined with Invalidate/Refresh) but it's a hack and you shouldn't use it. Plus the backgroundworker will leave your gui responsive, so you won't get the "not responding" thing when you click on it.
ScottyDoesKnow  Monday, September 28, 2009 8:44 PM

What you need is multithreading. If you do all your FTP stuff on your main thread, it's always busy and doesn't have time to update the display. Look intodoing all your FTP stuff in abackgroundworker, there are lots of resources and tutorials on this site and elsewhere online. Google is your friend.

ScottyDoesKnow  Monday, September 28, 2009 8:27 PM
The best option is to move your work into a background thread via a BackgroundWorker .

This will allow you to update your statusBox.Text property in the ProgressChanged event (keeping it on the UI thread), without blocking your user interface. Scenarios such as this are the perfect place for using a background thread and the BackgroundWorker component.
Reed Copsey, Jr. - http://reedcopsey.com
Reed Copsey, Jr.  Monday, September 28, 2009 8:28 PM
I agree you'd be best off using a background worker to move the processing code to another thread, however, failing that, try using statusBox.Refresh instead of Invalidate.

Invalidate requests a paint operation be performed... it basically sends a message to the textbox window saying paint, but that message gets held in the queue until the system is ready to deal with it.

Refresh on the other hand, sends the mssage and waits for it to be processed (I'm not sure if it bypasses the queue, or allows the queue to be processed or what internally) therefore, when the Refresh method returns the screen should actually have been updated, unlike Invalidate().

Calling Refresh() will slow your code down, since you will be waiting for the paint operation each time, but it probably won't matter all that much.
Yort  Monday, September 28, 2009 8:41 PM
Refresh won't work alone. Application.DoEvents() would (combined with Invalidate/Refresh) but it's a hack and you shouldn't use it. Plus the backgroundworker will leave your gui responsive, so you won't get the "not responding" thing when you click on it.
ScottyDoesKnow  Monday, September 28, 2009 8:44 PM
Hi,

I agree the background worker, or some kind of multi-threading at any rate, is a better idea. I believe, however, that Refresh will work. I haven't got time to test it right now, but I believe I used to do this sort of thing years ago before I discovered the backgroundworker/multi-threading. I could be wrong though.
Yort  Monday, September 28, 2009 8:46 PM
I tried using Refresh() Yort, but that didn't work.

Scotty - I will take a look at seeing if I can spawn off theFTP's in a background thread, and while I'm sure it will be beneficial to use the BackGround processing for other applications as well, it sure seems like over-kill for such a small application...all of the code works it just looks like it isn't doing much to the end-user and the Windows.Form shows "...not responding" in the Title Bar until the FTP completes.

Thanks for all of the input everyone! I sure appreciate it.
Code Lizard  Monday, September 28, 2009 8:55 PM
I tried using Refresh() Yort, but that didn't work.

Scotty - I will take a look at seeing if I can spawn off theFTP's in a background thread, and while I'm sure it will be beneficial to use the BackGround processing for other applications as well, it sure seems like over-kill for such a small application...all of the code works it just looks like it isn't doing much to the end-user and the Windows.Form shows "...not responding" in the Title Bar until the FTP completes.

Thanks for all of the input everyone! I sure appreciate it.

Ok, thanks for letting me know, I appreciate it.

The background worker component is probably the easiest way to implement the threading you need in this case. Having your app repotred as non responding isn't good... if it's not responding for a long period users will often kill it with task manager, hence the recomemndation for threading.
Yort  Monday, September 28, 2009 9:00 PM
Hi Code Lizard,

I am writing to check if you have made any progress on solving the issue. I quite agree with using multi-thread in this application. And also I think you can give Application.DoEvent a try. Here is the information about that method.
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx

If you have any problems, please feel free to tell us. If you can post more code, it will help us to understand the case clearly.

Sincerely,
Kira Qian
Send us any feedback you have about the help from MSFT at fbmsdn@microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework!
Kira Qian  Wednesday, September 30, 2009 3:59 AM
And also I think you can give Application.DoEvent a try. Here is the information about that method.
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx

I find it strange that amoderator would promote the use of Application.DoEvents(). It's a hack. I've yet to see an example where the usage of DoEvents couldn't be refactored out by doing it correctly. I've used it before in small personal applications to save time, but it's never the right way to keep the UI responsive.
ScottyDoesKnow  Wednesday, September 30, 2009 2:04 PM

Thank you Kira!

This is exactly what I was looking for. The code worked as it was and I was pretty sure that all I was really missing was the DoEvents( ) call to throw execution back to Windows for it to update the status message box.

While I agree with Scotty and Yort about it being better to make this small application truly multi-threaded, after a couple of days of trying to get it implemented using BackgroundWorker stuff, I was still struggling to get it working.

The Application.DoEvents( ) yielded the results I wanted and I am able to display status messages in a text box as the application progresses so that the end user will know that the application is actually doing something during its FTP.

Many thanks to you Kira, as well as the help from Yort and Scotty.

Code Lizard  Wednesday, September 30, 2009 3:16 PM
I'll keep it short, it is not on topic for this thread. I can think of only two things worse than using Application.DoEvents(): never using it because you think it is a hack. And replacing it when threading when DoEvents() can do the job too. Almost every Windows Forms program actually uses it, it just isn't obvious. When you call Form.ShowDialog(), you start a loop that calls DoEvents(). Nobody considers ShowDialog() bad, short from the awkwardness of modal dialogs. It's because it uses the 100 pound sledgehammer solution to the classic nested execution problems of DoEvents(): it disables all the controls so the user can't click on anything that causes trouble. Doing this yourself is just as effective, just iterate Application.OpenForms() and set Enabled = false on the forms. This can be endlessly refined.

So, DoEvents() is a bit tricky to get right. That pales in comparison to getting its alternative right. Threading is hard, you can tell from the many questions in these forums about it. Lord knows how many apps are running out there with subtle race conditions that randomly deadlock the program now and then. Especially databinding is evil in a threaded program, popular with programmers that are least likely to get threading right. The number of ways to shoot yourself in the foot with BGW doesn't justify its "oh, just use a BGW to do this" reputation.

Well, end of rant. This thread definitely requires a thread.



Hans Passant.
nobugz  Wednesday, September 30, 2009 3:40 PM
I agree with Hans... DoEvents exists for a reason and is sometimes appropriate... I just didn't think it would be that hard to implement the OP's code in a background worker, and that it would probably be a better if not quicker solution.

Also, did any one tell the OP to disable his controls while his loop ran if he used doevents ?
Yort  Wednesday, September 30, 2009 8:48 PM
I agree with Hans... DoEvents exists for a reason and is sometimes appropriate... I just didn't think it would be that hard to implement the OP's code in a background worker, and that it would probably be a better if not quicker solution.

Also, did any one tell the OP to disable his controls while his loop ran if he used doevents ?


Yort, who is the "OP" that you and Hans refer to? Is that me?

I haven't seen anything related to disabling the other controls while this is running. Why is this being recommended?

And I have successfully implemented multi-threaded asynchronous FTP's in a completely different piece of code. It took a weekend for me to figure it all out and to get it working like I wanted it to. It was NOT a trviail experience...it was very convoluted for someone unfamiliar with it. Still, the stuff I learned by coding up the asynch-FTP doesn't seem to translate to knowledge of how to implement BackGroundWorker threads...

The code functioned correctly without the DoEvents( ) call, it just wasn't displaying all of the status messages I was issuing to the form's text box. Re-writing the app to incorporate multi-threading was a LOT more time consuming than following my writes to the TextBox with a DoEvents( ) call.
Code Lizard  Wednesday, September 30, 2009 9:03 PM
Hi,

Yes, OP would be you (OP = Original Poster).

Disabling controls on the form while running a loop with doevents is generally a good idea because the call to DoEvents allows the controls to be activated. That means the button that started your loop can be clicked again, causing two simultaneous instances of the loop to run which might be a problem. Further, if the loop refers to values stored in controls on the form, rather than caching them into local variables at the start of the process, then the user can change the control values while the loop is running and message things up. They can also close the form, which will ususally result in an object disposed exception, since closing the form disposes it and it's controls/components, and the loop will probably refer toa method or property on the form or one of it's controls eventually.
Yort  Wednesday, September 30, 2009 9:15 PM
To be clear: my post was off topic for the thread. I'm sorry if that created confusion. Sounds to me you've solved your problem, please close the thread by marking it answered.
Hans Passant.
nobugz  Wednesday, September 30, 2009 10:02 PM
Hi Code Lizard,

You are welcome! I am glad I can help you. The thanks are also given to Scotty who posts the idea. Application.DoEvent can be a quick fix, but design it with multi-thread is a better solution. Hope you can take it next time.

Sincerely,
Kira Qian
Send us any feedback you have about the help from MSFT at fbmsdn@microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework!
Kira Qian  Thursday, October 01, 2009 1:26 AM

You can use google to search for other answers

Custom Search

More Threads

• cross thread & forms
• Paint Event Problem
• Secondary DNS Server Cannot be resolved
• Configuring the wireless network device to work as firewall...
• Help with a calendar control
• Linq Where and
• How to make mouse cursor disappear
• MonthCalendar Control BoldedDates issue
• Object reference not set to an instance of an object.
• Table