Použití BackgroundWorker v modulu.   otázka

VB.NET, Visual Studio

Vyrobil jsem si program, který kopíruje a zároveň zobrazuje graf, kolik toho již je zkopírováno. Aby vše chodilo plynule, použil jsem BackgroundWorker a kopírování jsem dal do samostatného modulu. BackgroundWorker jsem si deklaroval v Modulu; Public bw as New BackgroundWorker. Používám Listview jako zdrojový vstup, spolu s List(Of String). Pro čtení řádků používám For Each r as Listviewitem in lvZdroj.Items. lvZdroj.Items.Count mně však předává nulovou hodnotu. Když vyhodím BackgroundWorker, je vše v pořádku, akorát kopírování brzdí ostatní příkazy jako je čas a s oknem se nedá pohnout. Když dám vše do hlavního programu, tak to chodí, jak má. Může mně někdo poradit, jakým způsobem to mám udělat? Poslal bych zdrojový výpis, ale je trošku delší. Bude-li to však nezbytné, ořezám ho a pošlu jen to podstatné.

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

Použijte vlákna.

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

Dík za odpověď, ale já vůbec netuším, jak se to dělá. Nemůžete mně napsat kratičký příklad? Děkuji.

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

Backgroudworker do formuláře, nastavit WorkerReportsProgress = true, spustit RunWorkerAsync, zpracovává se požadavek v DoWork, kde lze případně zpracovat vstupní e.Argument, průběh metodou ReportProgress vyvolá událost ProgressChanged, kde aktualizujete progressbar či graf a při ukončení vyvolá událost RunWorkerCompleted, kde získáte výsledek pomocí e.Result, jako result lze vrátit případně chybu a otestovat, zda-li je result Exception či ne.

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

Dobrý den. Tohle všechno dělám běžně, ale já jsem chtěl použít modul, abych oddělil kopírování od Form1. Jakmile se dostanu do modulu, tak ListView, konkrétně lvSoubory.Items.Count hlásí nulu, jako kdybych měl lvSoubory úplně prázdný. To je to, co mně hlava nebere. BackgroundWorker jsem si deklaroval v modulu. Do modulu se dostanu v okamžiku, kdy stisknu tlačítko kopírovat. Tam už čeká Public Sub Kopiruj, kde mám bw.RunworkerAsync a v DoWork mám odskok na vlastní Public Sub KopieSouboru. Do proměné si nastavím počet souborů, které mám ve Form1; to jsou ty lvSoubory. Když dám v modulu pocet = lvSoubory.Items.Count, tak pocet = 0. Tady vám posílám okleštěný kód, ale to podstatné tam je.

'Form1 (pojmenoval jsem jej F1)
	
 Public Sub pbKopiruj_Click(sender As Object, e As EventArgs) Handles pbKopiruj.Click
		'Stisknutí Ikony (používám PictureBox místo tlačítek)
   Call Kopiruj()
 End Sub
	
'Tady je modul
		
 Public WithEvents bw As New BackgroundWorker
		
 Public Sub Kopiruj()
   bw.RunWorkerAsync()
 End Sub

 Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork
   Call Kopie()
 End Sub

 Public Sub Kopie()
   F1.Cursor = Cursors.WaitCursor
   Dim pocet As Integer = F1.lvSoubory.Items.Count
   For Each r As ListViewItem In F1.lvSoubory.Items
     fInfo = FileSystem.GetFileInfo(fList(r.Index))
     zdroj = fList(r.Index)
     cil = cesta & fInfo.Name
			
     Call Vypocty.Vypocet(podil, pricti, SIRKA, pocet) 'Místo ProgressBaru používám Panel, u kterého 
 zvětšuji šířku. Udělal jsem si svoje DLL. Mohu tak měnit barvu jak chci.
			
     pricti += podil
     F1.panBar.Width = pricti
     F1.panPod.Width = pricti + 2

     poc += 1
     proc = (poc / pocet) * 100
     F1.lbCelkem.Text = "Celkem: " & (proc).ToString("N1") & "%"
     r.Checked = True
     FileSystem.CopyFile(zdroj, cil, UIOption.OnlyErrorDialogs, UICancelOption.ThrowException)
   Next
    
   Beep()
   F1.lbCelkem.Text = "Kopírování skončilo"
   F1.Cursor = Cursors.Default
 End Sub

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

Dobry den,

uvnitr BackgroundWorkeru (DoWork) nemuzete primo pristupovat k objektum, ktere jsou ve Form1, protoze vtu chvili jste v dalsim vlakne ktere bezi samostatne.

Pokud chcete pristupovat k nejakym datum uvnitr BackgroundWorkeru pouzijte RunWorkerAsync(object arg) ve vasem pripade treba ...

bw.RunWorkerAsync(lvSoubory.Items)

pote v metode Do_work si objekt nactete a treba poslete do metody Kopie.

Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork
   
Call Kopie(e.Argument)
 End Sub
nahlásit spamnahlásit spam 0 odpovědětodpovědět

DoWork běží v jiném vlákně ať je ve formuláři nebo v modulu, kde navíc nemá ponětí o listview a počtu jeho items, navíc si způsobíš problémy s illegal cross thread calls. Pokud je cílem opakované použití nebylo by lepší použít vlastní třídu než modul nebo podědit backgroundworkrer?

Události ProgressChanged a RunWorkerCompleted vrací zpracování zpět do vlákna, kde je formulář, ale zde máš komplet úplně vše zcela běžně v DoWork.

Cesty ke kopírování můžeš přece předat skrzeva argument jako string array nebo list(of string):

    Private WithEvents bw As BackgroundWorker

    Private Structure BackgroundWorkerArguments
        Public source_files() As String
        Public destination As String
        Sub New(ByVal source() As String, ByVal destination As String)
            source_files = source
            destination = destination
        End Sub
    End Structure

    Sub RunWorkerJob(source() As String, destination As String)
        bw = New BackgroundWorker
        bw.WorkerReportsProgress = True
        bw.RunWorkerAsync(New BackgroundWorkerArguments(source, destination))
    End Sub

    Private Sub bw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
        Dim bwa As BackgroundWorkerArguments = e.Argument
        For i = 0 To bwa.source_files.GetUpperBound(0)
            'copy only
            bw.ReportProgress(i, bwa.source_files(i))
        Next
    End Sub

    Private Sub bw_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
        'update progress
        Debug.Print(String.Format("{0},{1}", e.ProgressPercentage, e.UserState))
    End Sub

    Private Sub bw_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
        'completed
        Debug.Print("Completed")
        bw = Nothing
    End Sub
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Lze nalézt přehršle příkladů, přidám alespoň jeden pro inspiraci :

Fast Copy With Progress Bar [VB NET]

https://www.youtube.com/watch?v=9r4VqP7k...

Pokud klepnete pod video "zobrazit více" , pak naleznete zdrojový kód v textovém souboru, kopírování je pomocí FileStream, je vidno, jak použít Invoke, aby bylo možné volat prvky na formuláři i z jiného vlákna přímo v události backgrounworkeru DoWork a jak aktualizovat progresbary a labely s informacemi o průběhu...

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

Děkuji za všechny typy. Použil jsem ten velký příklad a chodí to. Teď zkusím použít Invoke, protože o tom jsem neměl ani tušení. Taky už nejsem nejmladší a tak to tím omlouvám. Ještě jednou děkuji.

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