-2

I am using the following code.

Why does it not run properly ?

private void Form1_Shown(object sender, EventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
        Application.DoEvents();
        Thread.Sleep(200);

        progressBar1.Refresh();
        progressBar1.Value = i;
        progressBar1.CreateGraphics().DrawString(i.ToString() + "%",
            new Font("Arial", (float)8.25, FontStyle.Regular),
            Brushes.Black, new PointF(progressBar1.Width / 2 - 10,
                progressBar1.Height / 2 - 7));


    }
}

update :

Why does not always show the text ?

jack rasha
  • 85
  • 2
  • 2
  • 6
  • 5
    You're blocking the UI thread. Don't do that. Look at some of the related questions on the right hand side. – Jon Skeet Nov 24 '11 at 15:09
  • 1
    Also, in *most* cases, DoEvents = evil. (http://hashvb.earlsoft.co.uk/Why_DoEvents_Are_Evil) – Jason Down Nov 24 '11 at 15:12
  • @JonSkeet- just telling somebody to avoid blocking the UI thread doesn't help. (It'seasier said than done). Neither do the related questions on the right. I've asked a [follow-up question](http://stackoverflow.com/questions/34910022/why-does-the-text-on-my-asynchronous-progressbar-flicker) that demonstrates the difficulty. – kmote Jan 20 '16 at 20:44

2 Answers2

1

This works - although I'd set the thread-sleep to more than 200 ms. Your problem was that you did the work in the UI thread and this way it never gets updated. For better visibility, just change the font color:

 private void Form1_Load(object sender, EventArgs e)
{
  Task t = new Task(() => StartUpdate());
  t.Start();

  t.ContinueWith(task => Console.WriteLine("Done loading"));
}

 private void StartUpdate()
{
  for (int i = 1; i <= 100; i++)
  {
    UpdateProgressBar(i);
  }
}

private void UpdateProgressBar(int i)
{
  if (progressBar1.InvokeRequired)
  {
    progressBar1.Invoke(new Action<int>(UpdateProgressBar), new Object[] { i });
  }
  else
  {
    Thread.Sleep(200);
    progressBar1.Refresh();
    progressBar1.Value = i;
    progressBar1.CreateGraphics().DrawString(i.ToString() + "%", new Font("Arial",
                                          (float)10.25, FontStyle.Bold),
                                          Brushes.Red, new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
  }
} 
Alex
  • 7,901
  • 1
  • 41
  • 56
-2

Use this. There are good ways of doing this but as your question was why it wasn't working, its because of the Application.DoEvents();

    private void Main_Shown(object sender, EventArgs e)
    {
        for (int i = 1; i <= 100; i++)
        {
            progressBar1.Value = i;
            int percent = (int)(((double)(progressBar1.Value -progressBar1.Minimum) / (double)(progressBar1.Maximum - progressBar1.Minimum)) * 100);
            using (Graphics gr = progressBar1.CreateGraphics())
            {
                gr.DrawString(percent.ToString() + "%",  SystemFonts.DefaultFont, Brushes.Black, new PointF(progressBar1.Width / 2 - (gr.MeasureString(percent.ToString() + "%", SystemFonts.DefaultFont).Width / 2.0F), progressBar1.Height / 2 - (gr.MeasureString(percent.ToString() + "%", SystemFonts.DefaultFont).Height / 2.0F)));
            }
            System.Threading.Thread.Sleep(200);
        }
    }
Azhar Khorasany
  • 2,712
  • 16
  • 20
  • Your UI won't be updated neither because the for loop is in the same thread as the main thread (which is responsible to update your GUI). Just paste it into an empty form an add a progress bar - you'll see. – Alex Nov 24 '11 at 15:42
  • Well it will be because of the Thread.Sleep() method. I have tried that on a form already and it does work. The value in the Sleep should be 200 or more though. Have you tried it before down voting my thing? I bet you haven't because I have. – Azhar Khorasany Nov 24 '11 at 15:46
  • See somebody accepted my answer just now. Please try using the code in a dummy app before downvoting. I hope you will revert it. – Azhar Khorasany Nov 24 '11 at 15:47
  • I pasted your code as is in a empty project. And all I see is a full progress bar at the end. The form won't even show up during the "progress phase". How would Thread.Sleep in the thread which is supposed to update the GUI do anything good? – Alex Nov 24 '11 at 15:48
  • What Form event are you using? Are you using Form_Load()?? Look what I have used? Form_Shown() – Azhar Khorasany Nov 24 '11 at 15:51
  • I've used both, Form_Shown() shows the progress but the UI is blocked nontheless - try moving the window arround or even move the mouse. You'll notice that the drawn font gets overlapped. As Jon Skeet mentioned: You block the UI thread, and you shouldn't do that. – Alex Nov 24 '11 at 15:55
  • DoEvent is like *crossing the beams*... It's bad ;) And freezing the main UI thread is not a good practice either. – JiBéDoublevé Nov 24 '11 at 20:41