Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form Not Responding when any other operation performed in C#

Tags:

c#

winforms

I have a form (Developed in C# using VS2010) with a Progress Bar. It's kind of stopwatch form where I fill the progress bar in say 10secs.... As Time elapses, Progress bar fills accordingly.... Means after 5secs, Progress Bar will be filled 50% and so on....

I used a for loop to perform this operation:-

for(int count=0;count<200;count++)
{
   progbar.performstep();
   progbar.update();
   update();
   Thread.Sleep(50);
}

I have used Thread.Sleep of 50msec so that progress bar updates smoothly. For 1sec, it increments in steps.

Problem is if I do anyother operation like Moving this form or even clicking on another icon on desktops makes this form "Not Responding".... But it perfoms the operation and at the end of 10 secs, It regains it's state and shows the pop up indicating 10secs are elapsed with Progress Bar Full.

Thanks for help and Sorry for using such complicated language.

Regards, Swanand

Update: I solved this problem with the help of Answers below.... One common mistake I got to know is forgetting "Applications.DoEvents()" along with "update()".... If you enter this line, there are less chances of getting "hanged"!

like image 707
Swanand Avatar asked Feb 07 '11 07:02

Swanand


3 Answers

If you want to run your code you should put this code in a function and call this function with one thread.

 public static void fun1()
        {
            for (int i = 0; i <= 10; i++)
            {
                Console.Write("This is function1");
                Console.Write("\n");

            }

        }
  Thread firstthread = new Thread(new ThreadStart(fun1));

  firstthread.Start();
  firstthread.suspend();//whenever you want your current control to stop.

b'caz Thread.sleep(100) will stop the whole context not that particular you want..

like image 181
Vishal Patwardhan Avatar answered Oct 13 '22 09:10

Vishal Patwardhan


You're performing a long-running operation on the UI thread, which means that the UI "message loop" (responsible for handling events such as user input and updating the screen) doesn't get a chance to run.

You should perform the long-running operation on a different thread (whether one you create yourself or a background thread) and either use BackgroundWorker to easily update your progress bar, or use Control.Invoke/BeginInvoke to marshall a delegate call back to the UI thread when you need to update the UI. (You mustn't update controls from the wrong thread.)

If your only UI interaction is filling in a progress bar, I suggest using BackgroundWorker.

If you're not really doing "real" work, just waiting for time to pass, you could use a System.Windows.Forms.Timer instead of all of this, however. That will "tick" on the UI thread, but won't block the UI thread between ticks. You should only use this if you don't have a lot of work to do though - if it really is just updating a progress bar, not (say) processing a file etc. Note that you shouldn't rely on the timer firing exactly "on time" - you should probably set the position of the progress bar based on the observed time, rather than the observed number of ticks.

like image 21
Jon Skeet Avatar answered Oct 13 '22 11:10

Jon Skeet


You are blocking the UI thread, which means it isn't processing events such as "paint". To do this properly, you should be using something like BackgroundWorker, and just updating the UI from the progress event.

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Threading;

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyForm());
    }
}

class MyForm : Form
{
    Button btn;
    BackgroundWorker worker;
    ProgressBar bar;
    public MyForm()
    {
        Controls.Add(btn = new Button { Text = "Click me" });
        btn.Click += new EventHandler(btn_Click);

        Controls.Add(bar = new ProgressBar { Dock = DockStyle.Bottom, Visible = false, Minimum = 0, Maximum = 100 });

        worker = new BackgroundWorker { WorkerReportsProgress = true };
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        bar.Visible = false;
        if (e.Error != null)
        {
            Text = e.Error.Message;
        }
        else if (e.Cancelled)
        {
            Text = "cancelled";
        }
        else
        {
            Text = e.Result == null ? "complete" : e.Result.ToString();
        }
        btn.Enabled = true;
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int count = 0; count < 100; count++)
        {
            worker.ReportProgress(count);
            Thread.Sleep(50);
        }
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        bar.Value = e.ProgressPercentage;
    }

    void btn_Click(object sender, EventArgs e)
    {
        bar.Value = 0;
        bar.Visible = true;
        btn.Enabled = false;
        worker.RunWorkerAsync();
    }
}
like image 30
Marc Gravell Avatar answered Oct 13 '22 11:10

Marc Gravell