Форма ProgressBar висит посередине, значение обновлено из класса BackGroundWorker

1

я создал форму1 с кнопкой1, чтобы запустить задачу, которая будет обрабатываться на фоне с помощью BackGroundWorker в отдельном классе и отображать ProgressBar в отдельном окне.

моя проблема заключается в том, что процесс отлично работает, за исключением того, что задача выполнена, но прогрессная форма висит посередине.

Изображение 174551

ниже приведен класс BackGroundLoading

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;

namespace sample2
{
    public class BackgroundLoading
    {
        public BackgroundWorker Bw;
        public delegate void RunFunction();
        public RunFunction thisFunction;
        mycontrols.LoadProgress p = new mycontrols.LoadProgress();

        public BackgroundLoading(RunFunction newFunction)
        {
            thisFunction = newFunction;
            Bw = new BackgroundWorker();
            Bw.WorkerReportsProgress = true;
            Bw.DoWork += new DoWorkEventHandler(Bw_DoWork);
            Bw.ProgressChanged += new ProgressChangedEventHandler(Bw_ProgressChanged);
            Bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bw_RunWorkerCompleted);
        }

        public void Start()
        {
            Bw.RunWorkerAsync();
        }

        void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }
            if (e.Cancelled)
            {
                MessageBox.Show("Cancelled!");
            }
            else
            {
                MessageBox.Show("Completed!");
                p.Close();
            }

        }

        public void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            /// If I put 
            /// p.ProgBar.Value = e.ProgressPercentage;
            /// the progressbar hangs upon form show.
        }

        void Bw_DoWork(object sender, DoWorkEventArgs e)
        {
            p.Show();

            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; (i <= 100); i++)
            {
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    if (thisFunction != null)
                    {
                        thisFunction();
                        worker.ReportProgress((i * 1));
                        p.ProgBar.Value = i;   
                    }
                    else
                    {
                        MessageBox.Show("Error, no method found");
                    }
                }
            }

        }
    }
}

это код Form1.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace sample2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BackgroundLoading BL = new BackgroundLoading(workingmethod);
            BL.Start();
        }

        private void workingmethod()
        {
            System.Threading.Thread.Sleep(10);
        }

    }
}

это код для формы LoadProgress

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace sample2.mycontrols
{
    public partial class LoadProgress : Form
    {
        public LoadProgress()
        {
            InitializeComponent();
        }

        private void LoadProgress_Load(object sender, EventArgs e)
        {     

        }

    }
}

нет кода в форме progressbar, так как обновление выполняется в классе. не может найти причину зависания.

Заранее спасибо.

  • 0
    Вы пытались переместить p.Show(); из обработчика событий Bw_DoWork (вероятнее всего, будет работать ctor BackgroundLoading)? Элементы управления WinForms не должны быть доступны из фоновых потоков (DoWork запускается не из пользовательского интерфейса, фоновый поток). Доступ к свойствам Form или UserControl из любого потока, кроме потока пользовательского интерфейса, вызывает непредсказуемое поведение - то же самое относится и к p.ProgBar.Value = i; (Вы можете обновить это в событии ProgressChanged, которое правильно маршалируется в поток пользовательского интерфейса)
  • 0
    ты пытался отладить свой код?
Показать ещё 1 комментарий
Теги:
class
winforms
progress-bar
backgroundworker

1 ответ

0
Лучший ответ

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

public void Start()
{
    p.Show();

    Bw.RunWorkerAsync();
}

Затем вы можете совершать вызовы в форме в событии ProgressChanged, которое выполняется в потоке пользовательского интерфейса.

Удалите p.Show() и p.ProgBar.Value = i; из события DoWork - вы не хотите касаться нити пользовательского интерфейса из фонового потока.

public void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    p.ProgBar.Value = e.ProgressPercentage;
}

Наконец, закройте форму, когда BackgroundWorker будет завершен (что вы уже делаете):

void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    p.Close();
}
  • 0
    Спасибо, сэр, вы спасли меня на этом .. :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню