BackgroundWorker   zodpovězená otázka

C#, VB.NET, Komponenty, Threading

Dobrý den,potřeboval bych pomoct s komponentou Backgroundworker.Nikdy jsem se sní nesetkal.Abych to pochopil pustil jsem si Tutoriál na MSTV.Poté sem zkusil napsat ňejaký zkušební prográmek abych zkusil jestli to umím.Bohužel(program spadne),tady mám kód svého programu a byl bych moc rád kdyby mi to někdo vyjasnil(je to fakt pro mě premiéra).Děkuji.

    Dim a As Integer
    Dim pocitej As Integer
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ProgressBar1.Minimum = 0
        ProgressBar1.Maximum = 10000
        Label2.Text = "Nacitam"
        BackgroundWorker1.RunWorkerAsync()
    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        For a = 0 To 10000
            pocitej = Int(Rnd() * 10000)
            ListBox1.Items.Add(pocitej)
            ProgressBar1.Value = a
        Next
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Label2.Text = "Hotovo"
    End Sub

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Problém je, že v události DoWork pracujete s ovládacími prvky hlavního vlákna, a protože DoWork běží v odděleným vlákně, program ohlásí cross-thread exception a ukončí se.

Pro změnu progress baru slouží událost ProgressChanged. Jak s ní pracovat je vidět v ukázce na msdn

http://msdn.microsoft.com/en-us/library/...

Co se týče práce s ostatnímy ovládacímy prvky, budete si muset vypomoct delegáty metod a funkcí invoke. Jak se dělá tohle byste snad měl najít tady na fóru.

Hodně stěstí, ať se to podaří

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

BackgroundWorker sice zatím nepoužívám, ale myslel jsem že tato komponenta je dělaná právě na to, když např. z jiného vlákna chcete ovládat prvky na formuláři. Tedy že je zde zajištěna synchronizace, což by jste si s použitím "klasického" jiného vlákna musel psát sám (pokud to vůbec jde).

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

taky jsem si to myslel, narazil jsem právě na tyhle problémy... Nevim, většina kódů, který pracovaly s BackgroundWorkerem nepřistupovaly ke komponentám, a těch pár ostatních používalo delegáty.

Pořád tak trochu doufám že nám někdo tuhle problematiku osvětlí, třeba p. Herceg nebo p. Linhart. No uvidíme.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

No, já jsem s BackgroundWorkerek párkrát pracoval a pozoroval jsem několik věcí. Přímo z BackgroundWorkeru pracovat s komponentami na formu jde, vtip je ale v tom, že se s těmi komponentami nesmí pracovat nikde jinde. Takže je to o hubu přistupovat k nim přímo, protože nikdy nevíte, jestli komponenta není zrovna používaná. Řešením je ale událost WorkerProgressChanged. BackgroundWorkeru se musí nastavit ReportsProgress pozitivní a pak bude událost vyvolávat vždy, když zavoláte z handleru události DoWork BackgroundWorker.ReportWorkerProgress() nebo tak nějak. Tam dosadíte procentuálí postup (ale v podstatě tam můžete dávat čísla třeba od jedné do deseti, když si to znázornítě nějak rozumně v UI, takže třeba počet zpracovaných souborů a tak) a druhý, volitelný, parametr je UserState, což je objekt, který se předá. Ideální je dosadit anonymní objekt s příslušnými hodnotami a podle něj v handleru události WorkerProgressChanged nastavit změny v UI.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zde je snippet, který jsem na toto téma napsal.

http://www.vbnet.cz/snippet--52-zaklady_...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ano, BackgroundWorker je napsán pro použití ve Windows Forms tak, aby se nemusela zajišťovat synchronizace s UI. Jenže vy ho používáte špatně. V události DoWork má být veškerá náročná práce kterou chcete provádět ve vlastním vlákně a nic jiného. Veškeré notifikace o průběhu operace se provádějí zavoláním metody ReportProgress, která vyvolá událost ProgressChanged, ve které už je synchronizovaný přístup k ovládacím prvkům. Stejně tak dokončení operace je automaticky signalizováno vyvoláním události RunWorkerCompleted, která je rovněž synchronizovaná.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak teď už tomu rozumím. To jsem se právě nikde nedozvěděl, že se data dají předávat do události WorkerProgressChanged přes objekt UserState.

Díky za info

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Chci vám všem poděkovat za objasnění problému.Díky :)

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback