我的自定义progressBar表单在我显示时挂起

时间:2011-09-13 13:00:36

标签: c# visual-studio

我在这里制作了一个演奏进度条角色的表单是我制作的代码

  public partial class PXProgressBar : Form
    {
        public delegate bool CancelEvent();
        public event CancelEvent cancel_e;

        public Boolean ProcessCancelled
        {
            get;
            set;
        }
        public PXProgressBar(bool EnableCancel) 
        {
            InitializeComponent();
            ProcessCancelled = false;
            progressBar1.Minimum = 0;
            if (!EnableCancel)
                Cancelbtn.Visible = false;

        }
        public  void increament(int step)
        {
            if (progressBar1.Value < progressBar1.Maximum-1)
            {
                progressBar1.Value++;
                progressBar1.Caption = progressBar1.Value.ToString() + " of " + progressBar1.Maximum;
                progressBar1.Refresh();

            }

            else
            {
                progressBar1.Value++;
                progressBar1.Caption = progressBar1.Value.ToString() + " of " + progressBar1.Maximum;
                if (this.TopMost)
                    this.TopMost = false;
                this.Update();
                this.Hide();
                this.WindowState = FormWindowState.Minimized;
               // this.Dispose();
            }

        }
        public void SetMaximum(int MaximumValue)
        {
            if (MaximumValue <= 0)
            {
                progressBar1.Maximum = 0;
                return;
            }
            if (progressBar1.Minimum != 0 && MaximumValue < progressBar1.Minimum)
            {
                progressBar1.Maximum = progressBar1.Minimum;
                return;
            }
            progressBar1.Maximum = MaximumValue;


        }
        public void SetMinimum(int MinimumValue)
        {
            progressBar1.Value = 0;
            if (MinimumValue <= 0)
            {

                progressBar1.Minimum = 0;
                return;
            }
            if (progressBar1.Maximum != 100 && MinimumValue > progressBar1.Maximum)
            {
                progressBar1.Minimum = progressBar1.Maximum;
                return;
            }
            progressBar1.Minimum= MinimumValue;
        }
        public void SetTitle(string ProcessTitle)
        {
            this.ProgressTitlelb.Text =ProcessTitle;// ProcessTitle;
            //this.ProgressTitlelb.Left = (this.panel1.Width - this.ProgressTitlelb.Width) / 2;
            //this.ProgressTitlelb.Top = (this.panel1.Height - this.ProgressTitlelb.Height) / 2;
            this.Update();
        }

        private void Cancelbtn_Click(object sender, EventArgs e)
        {

            ProcessCancelled = true;
            bool disposeRequired =cancel_e();
            if(disposeRequired)
             this.Dispose();
        }

        private void PXProgressBar_Shown(object sender, EventArgs e)
        {
            this.Update();
        }

    }

我通过此代码调用表单

  if (ProgressBar == null)
   ProgressBar = new PXProgressBar(true);
   ProgressBar.SetTitle("Saving ...");
   ProgressBar.SetMinimum(0);
   ProgressBar.SetMaximum(100);
   ProgressBar.TopMost = true;
   ProgressBar.Show();
   Application.DoEvents();

关于过去几行是在一个线程中调用的 但当我运行它时表单挂起所以我不能在表单中设置一个取消按钮让用户取消操作

5 个答案:

答案 0 :(得分:2)

你的代码看起来应该没问题,所以我只能假设你在UI线程上进行长时间运行,这会导致UI看起来像挂起。您需要在后台线程上执行长时间运行的操作,以便UI线程保持足够的响应以响应按钮点击等。如果您咨询您的朋友Google,有很多关于此的文章。

有关此处的更多信息http://www.idevforfun.com/index.php/2010/01/10/windows-ui-threading/

我同意Skizz关于DoEvents的调用......只有极少数情况需要调用,而且大多数情况下它都在框架本身使用它。

答案 1 :(得分:1)

问题可能是DoEvents方法调用。来自this MSDN page

  

调用此方法会导致当前线程暂停   处理所有等待窗口消息。如果消息导致   要触发的事件,然后是应用程序代码的其他区域   执行。这可能会导致您的应用程序出现意外   难以调试的行为。如果您执行操作或   计算需要很长时间,通常最好执行   新线程上的那些操作。有关的更多信息   异步编程,请参见异步编程概述。

我认为DoEvents电话是不必要的。如果您需要在Show后暂停代码才能完成操作,请改用System.Threading.EventWaitHandle

答案 2 :(得分:1)

对于进度条,有一些链接可能对您有所帮助:

How do I implement a progress bar in C#?

希望得到这个帮助。

答案 3 :(得分:1)

您需要确保在主窗体线程上创建GUI元素,而不是从单独的线程创建。因此,您需要获得正在进行工作的线程以使主表单线程显示并更新进度条。这将需要一些重构。

所以,在你的工作线程中:

void DoWork () // of whatever it's called
{
  main_form.CreateProgressBar ();
  while (doing stuff)
  {
    main_form.IncrementProgressBar ();
    do stuff
  }
  main_form.DestroyProgressBar ();
}

以主要形式:

delegate void Callback ();

void CreateProgressBar ()
{
   if (InvokeRequired)
   {
     Invoke (new Callback (CreateProgressBar));
   }
   else
   {
     progress_bar = CreateProgressBar ();
   }
 }

void IncrementProgressBar ()
{
   if (InvokeRequired)
   {
     Invoke (new Callback (IncrementProgressBar ));
   }
   else
   {
     progress_bar.IncrementProgressBar ();
   }
 }

void DestroyProgressBar ()
{
   if (InvokeRequired)
   {
     Invoke (new Callback (DestroyProgressBar));
   }
   else
   {
     progress_bar.Close ();
     progress_bar = null;
   }
 }

InvokeRequired确定调用线程是否与GUI线程相同。如果调用线程不是GUI线程,则Invoke用于更改线程上下文。这是同步版本,在调用的方法完成之前不会完成。有一个名为BeginInvoke的异步版本,但实际上并不需要这样做。

答案 4 :(得分:0)

只需为进度条创建其他线程并在后台使用它