我制作了一个表格,起着进度条的作用,这是我制作的代码

  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();


关于过去的几行是在一个线程中称为
但是当我运行它时,窗体挂起,因此我无法在窗体中设置“取消”按钮,以允许用户取消操作

最佳答案

您需要确保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的异步版本,但这实际上并不需要您做。

08-26 16:21
查看更多