backgroundworker i zatrzymywanie zdarzenia

0

Cześć.

Mam problem z zatrzymywaniem zdarzenia w backgroundworkerze, które wykonuje się na bazie danych dłuższy czas. Dodalem komentarz w kodzie co chcialbym moc zatrzymywac w kazdym momencie, ponieważ bywa tak ze zapiszDGV() może się wykonywać dość długo, w zależności od przekazanego zapytania. Nie wiem natomiast jak to obsłużyć? Wątki to póki co trochę czarna magia, poza najprostszym - backgroundworkerem - który jest dość łatwy w implementacji i obsłudze (jak dla mnie...).
Program będzie miał docelowo wykonywać takie pobieranie i zapisywanie w pętli, więc dodatkowo jakby ktoś mógł mi podpowiedzieć jak w m_oBackgroundWorker_DoWork wymusić aby jedno zadanie czekało drugie? Ponieważ też zauważyłem, że jeśli zapiszDGV() trwa nieco dłużej, to wychodzi ze statusem "Pobranie niepomyslne" i przechodzi do następnej iteracji.

Kod wygląda mniej więcej tak:

funkcja wykonujaca zapytanie do bazy -

public void datgs(out string textbox, string zapytanie, ref DataTable table, OdbcConnection conn, OdbcDataAdapter dadapter)
        {
            try
            {
                conn.Open();

                dadapter = new OdbcDataAdapter(zapytanie, conn);
                table = new DataTable();
                dadapter.Fill(table);

                textbox = "Pobranie pomyslnie" + "\n";
            }
            catch
            {
                textbox = "Pobranie niepomyslnie" + "\n";
            }
            finally
            {
                //zapytanie = "";
                conn.Close();
            }
       }

        public void zapiszDGV() //laduje tabele do dataGridView2
        {
            try
            {
                dataGS.datgs(out zdarzenie, zapytanie, ref table2, conn, dadapter);
                
                dataGridView2.DataSource = table2;
                zapytanie = "";
            }
            catch
            {
                zdarzenie = "Pobranie niepomyslne" + "\n";
            }
        }

wywolanie backgroundworkera i jego obsluzenie -

        private void button1_Click(object sender, EventArgs e)
        {
            ilosc_zapytan = 0;
            if (null == m_oBackgroundWorker)
            {
                m_oBackgroundWorker = new BackgroundWorker();
                m_oBackgroundWorker.DoWork += new DoWorkEventHandler(m_oBackgroundWorker_DoWork);
                m_oBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oBackgroundWorker_RunWorkerCompleted);
                m_oBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(m_oBackgroundWorker_ProgressChanged);
                m_oBackgroundWorker.WorkerReportsProgress = true;
                m_oBackgroundWorker.WorkerSupportsCancellation = true;
            }
            zapytanie = "";
            m_oBackgroundWorker.RunWorkerAsync();
        }

        void m_oBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) //wykonuje zadanie w drugim wątku
        {
            //Thread.Sleep(500);
            if (ilosc_zapytan == 0)
            {
                if (m_oBackgroundWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                    //break;
                }
                //pobranie sql
                pobierzSQL.pobierzSQL(out zdarzenie, ref zapytanie, ilosc_zapytan, combobox, conn);
                m_oBackgroundWorker.ReportProgress(i++);
                //pobranie sciezki
                pobierzSciezke.pobierzSciezke(out zdarzenie, conn, ilosc_zapytan, ref sciezka, ref nazwa_pliku, combobox, zapytanie);
                m_oBackgroundWorker.ReportProgress(i++);
                //ladowanie DGV
                zapiszDGV(); //<== to chcialbym moc zatrzymywac w kazdym momencie
                m_oBackgroundWorker.ReportProgress(i++);
                //zapis raportu
                zapiszRaport();
                m_oBackgroundWorker.ReportProgress(i++);
                i = 0;
            }
            else
            {
                while (ilosc_zapytan > 0)
                {
                    if (m_oBackgroundWorker.CancellationPending)
                    {
                        e.Cancel = true;
                        break;
                    }
                    //pobranie sql
                    pobierzSQL.pobierzSQL(out zdarzenie, ref zapytanie, ilosc_zapytan, combobox, conn);
                    m_oBackgroundWorker.ReportProgress(i++);
                    //pobranie sciezki
                    pobierzSciezke.pobierzSciezke(out zdarzenie, conn, ilosc_zapytan, ref sciezka, ref nazwa_pliku, combobox, zapytanie);
                    m_oBackgroundWorker.ReportProgress(i++);
                    //ladowanie DGV
                    zapiszDGV(); //<= jesli trwa dluzej to przechodzi ze statusem "Pobranie niepomyslne" i przechodzi do następnej iteracji
                    m_oBackgroundWorker.ReportProgress(i++);
                    //zapis raportu
                    zapiszRaport();
                    m_oBackgroundWorker.ReportProgress(i++);
                    ilosc_zapytan--;
                }
                i = 0;
                ilosc_zapytan = 0;
            }
        }

        void m_oBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) //pobiera informacje o zdarzeniach z 2 watku i wypluwa je do richTextBoxa1
        {
             AppendLog(zdarzenie);
        }

        void m_oBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                backgroundWorker1.CancelAsync();
                backgroundWorker1.Dispose();
                AppendLog("Wykonywanie raportu przerwane" + "\n");
                AppendLog("------------------------------------------" + "\n");
            }
            else
            {
                backgroundWorker1.CancelAsync();
                backgroundWorker1.Dispose();
                AppendLog("Wykonywanie raportu zakonczone" + "\n");
                AppendLog("------------------------------------------" + "\n");
            }
        }
0

Co to za spaghetti? Ktoś się w tym bałaganie orientuje? Jak można mieszać logikę biznesową z prezentacją i dostępem do danych?

0

Na szczęście nie jestem programistą z zawodu, potrzebuję tylko takiego programu, który mi będzie wykonywał zapytania z bazy i je zapisywał do podanego zasobu, więc go stworzyłem, a raczej tworzę... Chodzi tylko o to by działał i się nie wysypywał, reszta jest mało istotna.

2

nie mozesz zatrzymac w dowolnym momencie wykonywania kodu nad ktorym nie masz kontroli

masz te dwie linijki w kodzie

                dataGS.datgs(out zdarzenie, zapytanie, ref table2, conn, dadapter);
 
                dataGridView2.DataSource = table2; 

ale w datgs znowu korzystasz juz z gotowych rozwiazan. Wiec jezeli tam cos dziala, to nie mozesz przerwac. Nie wspominajac o przypisaniu do DataSource Twojej tabeli

Jezeli napisalbys wlasna obsluge bazy to moglbys miec, ze sprawdzasz warunek co X czasu a w warnku mialbys sprawdzenie swojego przerwania.

Ale i tak zapewne do bazy laczysz sie ktora tez jest zewnetrzna (nie napisana przez Ciebie) ktore wystawia jakies tam funkcje (API). Nie masz kontorli nad tym co robi to API wiec ponownie. Nie mozesz przerwac bo nie masz wladzy nad tym co to tam robi

Jezeli chcesz moc przerywac w dowolnym momencie to musialbys napisac wszystko samemu.

Sadze ze lepsza opcja dla Ciebie bedzie po prostu ustawienie timeoutu na cos co Ciebie zadowala. Po tym timeoucie funkcje zewnetrzne po prostu przerwa swoje dzialanie

0

Dziękuję za wyjaśnienie, oczywiście korzystam z zewnętrznej bazy.

Istnieje może sposób na "zakomunikowanie" zewnętrznemu podmiotowi funkcji Abort dla zapytania? Coś jak w SQL Developerze "Cancel task"?

Funkcje timout i tak muszę zaprogramować docelowo, będzie ona dla każdego zapytania na około 2h, chciałem mieć po prostu większą kontrolę nad samym wykonaniem

1

to wszystko zalezy od zewnetrznej bazy ktorej korzystasz. Musisz poszukac czy maja cos takiego dostepgo przez API i wtedy bys mogl to wywolac z poziomu swojego kodu.

A czemu nie chcesz uzyc timeout? wiekszosc funkcji powinno meic timeout

0

timout będzie podawany do każdego zapytania osobno, ale będzie on dość ogromny. Obecnie są to wartości między 120 a 360 minut. Chciałem mieć oprócz niego jakąś możliwość ręcznego przerwania :)

1

musisz poszukac czy Twoja baza danych przyjmuje cos takiego jak terminate / abort (etc). Jezeli tak, to mozesz wtedy wyslac taka informacje do bazy i przerwie dzialanie transakcji

0

dzięki wielkie, będę szperał :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1