BackgroundWorker.ReportProgress

BackgroundWorker.ReportProgress
Z3
  • Rejestracja:ponad 14 lat
  • Ostatnio:ponad 14 lat
  • Postów:3
0

Witam

wrzuciłem backgroundworker + progressbar do swojego programu, wszystko działa ok, z tym, że chciałbym przenieść zawartość metody, o której wykonywaniu się informuje progressbar do osobnej metody w specjalnie wydzielonej klasie. I tu pojawia się problem. Jak wtedy informować backgroundworkera o postępie w wykonywaniu się metody, kiedy nie mamy dostępu do licznika pętli, który ukryty jest jak już wcześniej napisałem w metodzie innej klasy? Z góry dziękuję za wszelkie sugestie :)

Bardziej obrazowo:

Kopiuj
  private void bWsynchro_DoWork(object sender, DoWorkEventArgs e)
        { 
          Obliczenia.mojaMetoda(); 
         }
edytowany 1x, ostatnio: z3nek
adams85
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 14 lat
0

Chodzi ci o ProgressChanged?
Albo niech Obliczenia.mojaMetoda() po prostu zwraca skok na progressbar'ze(wtedy użyjesz tego jako BW.ReportProgress(Obliczenia.mojaMetoda())). Albo możesz w tej klasie utworzyć metodę o sygnaturze takiej jak ProgressChangedEventHandler i podpiąć ją pod ProgressChanged twojego BW. Dodatkowo przekazać tej klasie referencję do progressbara, którym ma poruszać, lub zrobić to samo za pomocą delegatów.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:4 dni
  • Lokalizacja:Wrocław
0

Delegaty dobry pomysł, referencja do progressbara w klasie średni - nie powinno się wiązać logiki obliczeniowej z GUI tak silnie.

adams85
Wiem, ale tak jest łatwiej, do ogarnięcia na początek, więc jako alternatywę podałem właśnie delegaty ;)
Z3
  • Rejestracja:ponad 14 lat
  • Ostatnio:ponad 14 lat
  • Postów:3
0

Kod klasy formatki, na której umieszczony jest progressBar:

Kopiuj
 
    public partial class Synchro : Form
    {
        Downloader dwn;  
        int progress;
        public Synchro()
        {
            InitializeComponent();
            dwn = new Downloader();
            bWsynchro.DoWork += new DoWorkEventHandler(bWsynchro_DoWork);
            bWsynchro.ProgressChanged += new ProgressChangedEventHandler(bWsynchro_ProgressChanged);
            bWsynchro.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bWsynchro_RunWorkerCompleted);
        }
        private void bWsynchro_DoWork(object sender, DoWorkEventArgs e)
        {
            bWsynchro = sender as BackgroundWorker;
            if ((bWsynchro.CancellationPending == true)) 
            {
                e.Cancel = true;
            }
            else 
            {
                dwn.Obliczenia(); 
                bWsynchro.CancelAsync(); 
            }
        }
        private void bWsynchro_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progress = e.ProgressPercentage;
        }
        public void pUpdate(int i)
        {
            Console.WriteLine(i);
        } 
        private void bWsynchro_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        { }
        private void bStart_Click(object sender, EventArgs e)
        {
            if (bWsynchro.IsBusy != true)
            {
                bWsynchro.RunWorkerAsync();   
            }
        }
    }

Kod klasy odpowiadającej za żmudne obliczenia:

Kopiuj
 
    class Downloader
    {
        public static int progress;
        public void Obliczenia()
        {
            Synchro s = new Synchro(); 
            try
            {
                        for (int i = 0; i < k; i++)
                        {
                            progress = Convert.ToInt32(Math.Round(licznik * 100.0 / n, 2));
                            s.pUpdate(progress); 
                        }
            }
            catch (SoapException soapex)
            { }
        } 
    }
edytowany 5x, ostatnio: z3nek
adams85
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 14 lat
1

Po pierwsze:

Kopiuj
  Synchro s = new Synchro();

</quote> Tworzysz NOWY OBIEKT klasy synchro (twojej formy z progressbarem)

Kopiuj
 s.pUpdate(progress); 

</quote> Robisz update na NOWYM OBIEKCIE klasy synchro, TO NIE ZMIENI niczego na twojej formie glownej.

Po drugie: chyba nie zrozumiałeś do końca istoty działania BW.
Moja rada jest taka: daruj sobie BW w formie, skoro chcesz żeby cała operacja była wykonywana w klasie Downloader, to tam utwórz sobie BW. Definicja DoWork bedzie w klasie Downloader, a w klasie Synchro ustawisz tylko ProgressChanged i RunWorkerCompleted tegoż BW. Dzięki temu Downloader będzie wykonywał swoją operację, w międzyczasie raportował progres do formy głównej(bez brutalnego dłubania w jej zmiennych), a po zakończeniu operacji zaraportuje koniec pracy.

Nie wiem czy to pominąłeś w umieszczonym tu kodzie, czy nie masz tego u siebie, ale musisz ustawić jeszcze dwie flagi na true: WorkerSupportsCancellation(żeby można było anulować BW) i WorkerReportsProgress(żeby można było raportować postęp) bez tego dostaniesz wyjątkami po oczach ;) Dodatkowo używając tego

Kopiuj
if ((bWsynchro.CancellationPending == true))
{
e.Cancel = true;
}

w tym miejscu gdzie użyłeś nic ci nie da. Sprawdzanie tej flagi powinieneś wstawić w miejsce tej pętli:

Kopiuj
for (int i = 0; i < k; i++)
{
//Tu sprawdzasz czy w miedzyczasie nie zostalo anulowane - jeżeli tak to daj return, żeby wyszło z DoWorka, 
//ustawienie jedynie Cancel = true tak naprawdę nic ci nie da 
progress = Convert.ToInt32(Math.Round(licznik * 100.0 / n, 2));
//Tu update 
} 
edytowany 4x, ostatnio: adams85
Z3
  • Rejestracja:ponad 14 lat
  • Ostatnio:ponad 14 lat
  • Postów:3
0
adams85 napisał(a)

Moja rada jest taka: daruj sobie BW w formie, skoro chcesz żeby cała operacja była wykonywana w klasie Downloader, to tam utwórz sobie BW. Definicja DoWork bedzie w klasie Downloader, a w klasie Synchro ustawisz tylko ProgressChanged i RunWorkerCompleted tegoż BW. Dzięki temu Downloader będzie wykonywał swoją operację, w międzyczasie raportował progres do formy głównej(bez brutalnego dłubania w jej zmiennych), a po zakończeniu operacji zaraportuje koniec pracy.

Działa! O takie szybkie i proste rozwiązanie właśnie mi chodziło, wielkie dzięki adams85! :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.