Моя пользовательская форма progressBar зависает, когда я ее показываю - PullRequest
1 голос
/ 13 сентября 2011

Я сделал форму, которая играет роль индикатора прогресса, вот код, который я сделал

  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 ]

2 голосов
/ 13 сентября 2011

Ваш код выглядит так, как будто он должен быть в порядке, поэтому я могу только предположить, что вы выполняете длительную операцию в потоке пользовательского интерфейса, из-за которой пользовательский интерфейс выглядит как зависший.Вам необходимо выполнять длительные операции в фоновом потоке, чтобы поток пользовательского интерфейса оставался достаточно отзывчивым, чтобы реагировать на нажатия кнопок и т. Д. Если вы проконсультируетесь со своим другом Google, вы найдете много статей об этом.

Подробнее об этом здесь http://www.idevforfun.com/index.php/2010/01/10/windows-ui-threading/

Я согласен со Skizz в отношении вызова DoEvents ... есть только несколько редких случаев, когда этот вызов необходим, и в основном его в самой структуречто это привыкает.

1 голос
/ 14 сентября 2011

Необходимо убедиться, что элементы графического интерфейса создаются в главном потоке формы, а не из отдельного потока.Итак, вам нужно получить поток, который выполняет всю работу, чтобы основной поток формы отображал и обновлял индикатор выполнения.Это займет немного рефакторинга.

Итак, в вашем рабочем потоке:

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, но она не нужна для того, что вы делаете.

1 голос
/ 13 сентября 2011

Там может быть какая-то ссылка для вас о прогрессбар:

Как реализовать индикатор выполнения в C #?

Надеюсь, эта помощь.

1 голос
/ 13 сентября 2011

Возможно, проблема в вызове метода DoEvents.Начиная с этой страницы MSDN :

Вызов этого метода приводит к приостановке текущего потока, пока обрабатываются все сообщения окна ожидания.Если сообщение вызывает событие, которое может быть вызвано, тогда могут выполняться другие области кода вашего приложения.Это может привести к тому, что ваше приложение будет демонстрировать неожиданное поведение, которое трудно отладить.Если вы выполняете операции или вычисления, которые занимают много времени, часто предпочтительнее выполнять эти операции в новом потоке.Для получения дополнительной информации об асинхронном программировании см. Обзор асинхронного программирования.

Я не думаю, что вызов DoEvents необходим.Если вам нужно остановить код после Show для завершения операции, используйте вместо этого System.Threading.EventWaitHandle.

0 голосов
/ 13 сентября 2011

Просто создайте другой поток для прогрессбара и используйте его в фоновом режиме

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...