-3

I have a button in a form. When the button is clicked, the button click function is called. In the function at first another form (let's call it object form2 from class Form2) it is created with some objects including labels and progress bars (these objects are created through form2 constructor). Then form2.Show() is called. Then a while loop comes which by end of it some variables are updated. I use these variables to update several objects in form2. The problem is that the form objects are not shown rightly until the button click function is finished. For example instead of labels, white rectangles are shown. I tried using Thread.Sleep(1000) after my while to see if objects are shown rightly but it didn't have any effect on form2 shape. Then I used a MessageBox.Show() after my while and it worked surprisingly! Objects were shown correctly in form2. I appreciate if anyone could say what is the problem and how I can solve it.

Diamond
  • 598
  • 5
  • 15

2 Answers2

0

You're blocking the UI thread, thus preventing updates until you release the UI thread to continue handling other messages sent to it.

If you have long running CPU bound work, you should be offloading it to another background thread. If you have IO or other non-CPU bound work to do you should be doing it asynchronously, rather than synchronously blocking on it, so that the UI thread can continue processing other events.

Servy
  • 202,030
  • 26
  • 332
  • 449
-1

If you do heavy work you really should do it in a background worker.

Meanwhile (to get it work) you can call Application.DoEvents which should give your controls "time" to update.

Taken from MSDN: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents%28v=vs.110%29.aspx

foreach (string file in files )
{
    System.IO.FileInfo fileInfo = new System.IO.FileInfo(file);
    System.IO.FileStream fileStream = fileInfo.OpenRead();
    pictureBox1.Image = System.Drawing.Image.FromStream(fileStream);
    Application.DoEvents();
    fileStream.Close();

    // Call Sleep so the picture is briefly displayed,  
    //which will create a slide-show effect.
    System.Threading.Thread.Sleep(2000);
}

If you are interested in more details, Hans has a good explanation: https://stackoverflow.com/a/5183623/2243584

One could always argue about the use of Application.DoEvents but as Hans stated ShowDialog uses it internally as well - thats the reason why your MessageBox example worked!

Community
  • 1
  • 1
toATwork
  • 1,335
  • 16
  • 34
  • 1
    This is *not* an appropriate use of `DoEvents`. Just because there are situations in which it can be appropriate doesn't mean you should just use it all over the place. It should be used *very* rarely, and only by someone who understand to a good depth of what exactly it's doing, when it is and isn't appropriate, and what the consequences of using it are. This is most certainly a case where the work should be either done asynchronously or in a non-UI thread. Your use of `DoEvents` will create a program with a very poor user experience, and quite a lot of bugs/race conditions. – Servy Jan 31 '14 at 18:35