[VB.NET 2005] Form en backgroundworker

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
Hallo,

Ik heb de volgende situatie;
Ik heb een desktop, met daarbij een plugin (in dit geval 1)
Die plugin bevat een aantal formulieren.

Wanneer ik gewoon
dim frm as new form()
frm.show()
gebruik is er niets aan de hand.
Echter wanneer ik een backgroundworker wil gebruiken, omdat het laden van een formulier even kan duren omdat er veel uit de database gehaald moet worden, blijft het formulier vast.

Er treedt geen exception op, en alle functies m.b.t. het ophalen van de data worden ook juist uitgevoerd. Aan het eind van het laden komt her formulier dus naar voren (focus) en vervolgens niets. Dan reageert het form niet meer...

heeft er iemand enig idee waar de fout zit?

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Wat voer je asynchroon uit, de show method?

Als je hem ook in een anderen thread initializeerd vind .NET 1.1 dat allemaal niet zo leuk, weet niet hoe het met 2.0 zit maar lijkt mij hetzelfde verhaal. Waarom duurt het initializeren zo lang, een ctor mag nooit veel tijd trekken.

Database acties oid moeten ook niet in de ctor zitten mocht dit het geval zijn.

[ Voor 94% gewijzigd door pjvandesande op 25-10-2005 17:29 . Reden: ik edit teveel ]


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
questa schreef op dinsdag 25 oktober 2005 @ 17:27:
Wat voer je asynchroon uit, de show method?
code:
1
2
3
        BackgroundWorker1.ReportProgress(25)
        frm.Show()
        BackgroundWorker1.ReportProgress(100)

(let niet op de naamgeving, dit is enkel testen)

Dat is het enige wat er in staat.
Eerst had ik ook de declaratie in diezelfde methode staan, maar die heb ik nu bovenaan in de class (form) gezet, maar dat maakt geen verschil./


edit:
nee de databasecommunicatie zit in het load event en niet in de constructor.

[ Voor 9% gewijzigd door Rhapsody op 25-10-2005 17:31 ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:36
questa schreef op dinsdag 25 oktober 2005 @ 17:27:
Als je hem ook in een anderen thread initializeerd vind .NET 1.1 dat allemaal niet zo leuk, weet niet hoe het met 2.0 zit maar lijkt mij hetzelfde verhaal. Waarom duurt het initializeren zo lang, een ctor mag nooit veel tijd trekken.
Of dat nu in .NET is of niet in .NET, dat is windows die dat niet zo leuk vind.

Wat doet die backgroundworker precies ?

[ Voor 5% gewijzigd door whoami op 25-10-2005 20:18 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
whoami schreef op dinsdag 25 oktober 2005 @ 20:17:
[...]
Of dat nu in .NET is of niet in .NET, dat is windows die dat niet zo leuk vind.

Wat doet die backgroundworker precies ?
hoe bedoel je?

Dat is een standaard component bij vs.net 2005 waarmee je heel eenvoudig bepaalde zaken in een nieuwe thread kan laten uitvoeren.

Ik wil namelijk de gebruiker op de hoogte stellen dat er het een en ander ingeladen moet worden.

Edit:
Hoewel ik nu niet meer op mijn stage ben heb ik wel nog getest daar dat het niet aan de verbinding met de database lag. Een simpel 'about' form bleef ook hangen...

[ Voor 16% gewijzigd door Rhapsody op 25-10-2005 20:33 ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:36
Rhapsody schreef op dinsdag 25 oktober 2005 @ 20:28:
[...]

hoe bedoel je?

Dat is een standaard component bij vs.net 2005 waarmee je heel eenvoudig bepaalde zaken in een nieuwe thread kan laten uitvoeren.
Ja dat weet ik wel, maar je moet die backgroundworker toch iets laten doen ?
Wat doet die background-worker ?
Je geeft die background worker toch een method oid mee, die hij op een andere thread moet uitvoeren ?

Die backgroundworker is trouwens afaik niet veel meer als zoiets
[rml]whoami in "[ C#] button.Show() vanuit anderen Thread"[/rml]

[ Voor 13% gewijzigd door whoami op 25-10-2005 20:42 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Waar gebeurt nou de havy load precies? In het Load even van het Form?

Het is misschien een beter idee om een method te maken, bijvoorbeeld een Init() method.
De Init method voer je uit in een anderen Thread. Zodra de Init() klaar is vuur je een OnInitFinished event oid en roep je de Show() method aan van je Form.

In het load event van je Form donder je de geladen data in je GUI, mocht dit nodig zijn.

Kun je ons iets meer details geven van wat en weer er precies dure dingen plaatsvinden?

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
Vervelende is dat ik nu niet op mijn stage ben en dus die code niet bij de hand heb.


In de constructor van het te laden formulier gebeurt niets speciaals.

In de _load function (load event dus) worden diverse queries via een databaseobject uitgevoerd en worden de resultaten daarvan in enkele dropdownboxen geplaatst.

Maar daar kan de fout niet zitten, want als ik die eruit haal loopt het formulier ook vast.


In de backgroundworker functie DoWork() gebeurt enkel dit:
code:
1
2
dim frm as new frmAbout()
frm.show()

Met daar tussen in dan enkele reportprogress aanroepen.

Alle andere forms, lopen niet vast en kan ik blijven gebruiken.

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Rhapsody schreef op dinsdag 25 oktober 2005 @ 20:55:
In de _load function (load event dus) worden diverse queries via een databaseobject uitgevoerd en worden de resultaten daarvan in enkele dropdownboxen geplaatst.
In je load event horen geen dingen die exceptions kunnen veroorzaken. Dan gaat echt alles mis :)
In de backgroundworker functie DoWork() gebeurt enkel dit:
code:
1
2
dim frm as new frmAbout()
frm.show()

Met daar tussen in dan enkele reportprogress aanroepen.

Alle andere forms, lopen niet vast en kan ik blijven gebruiken.
Zoals al eerder gemeld moet je niet een Form initializeren in een anderen Thread dan je main thread.

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
questa schreef op dinsdag 25 oktober 2005 @ 20:57:
[...]


In je load event horen geen dingen die exceptions kunnen veroorzaken. Dan gaat echt alles mis :)


[...]


Zoals al eerder gemeld moet je niet een Form initializeren in een anderen Thread dan je main thread.
Ok, dus dan zou ik op dat formulier zelf een nieuwe thread moeten aanmaken welke de data ophaalt?

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Rhapsody schreef op dinsdag 25 oktober 2005 @ 21:00:
[...]
Ok, dus dan zou ik op dat formulier zelf een nieuwe thread moeten aanmaken welke de data ophaalt?
Nee, doe gewoon iets als:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private FrmMain _frmMain = null;

private void button1_Click(object sender, System.EventArgs e)
{
    _frmMain = new FrmMain();
    frmMain.InitComplete += new EventHandler(frmMain_InitComplete);

    Thread t = new Thread(new ThreadStart(frmMain.Init()));
    t.Start();
}

private void frmMain_InitComplete(object sender, System.EventArgs e)
{
    Debug.Assert(_frmMain != null, "_frmMain kan niet null zijn hier! Grr!");
    _frmMain.Show();
}

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
daar ga ik morgen ff mee spelen, alvast bedankt :)

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:36
Je moet idd geen forms in aparte threads gaan maken.

InitComplete is hier een custom event als ik het goed begrijp ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

whoami schreef op dinsdag 25 oktober 2005 @ 21:24:
Je moet idd geen forms in aparte threads gaan maken.

InitComplete is hier een custom event als ik het goed begrijp ?
Ja, word gewoon afgevuurt als de init goed gelukt is en klaar.

Handig als je dus de Init method uitvoer in een anderen Thread, zodra hij klaar is roep je daar gewoon Form.Show aan.

Tussendoor kun je nog een event gooien die het persentage verhoogt van het Init process.

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
questa schreef op dinsdag 25 oktober 2005 @ 21:48:
[...]


Ja, word gewoon afgevuurt als de init goed gelukt is en klaar.

Handig als je dus de Init method uitvoer in een anderen Thread, zodra hij klaar is roep je daar gewoon Form.Show aan.

Tussendoor kun je nog een event gooien die het persentage verhoogt van het Init process.
Ik heb jouw code fragment even vertaald naar VB.NET, maar ik lijk tegen precies hetzelfde aan te lopen:

Mainform:
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
    Private _frmDialog As frmDialog = Nothing
    Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click
        _frmDialog = New frmDialog()
        AddHandler _frmDialog.initcomplete, AddressOf Me.frmMain_InitComplete
        Dim t As Thread = New Thread(New ThreadStart(AddressOf frmDialog.init))
        t.Start()
    End Sub

    Private Sub frmMain_InitComplete(ByVal sender As Object, ByVal e As System.EventArgs)
        Debug.Assert(_frmDialog IsNot Nothing, "_frmDialog kan niet null zijn hier! Grr!")
        frmDialog.Show()
    End Sub


Dialog:
Visual Basic .NET:
1
2
3
4
5
6
    Public Event initcomplete(ByVal sender As Object, ByVal e As System.EventArgs)

    Sub init()
        MessageBox.Show("potverdikkie")
        RaiseEvent initcomplete(Me, Nothing)
    End Sub

[ Voor 5% gewijzigd door Rhapsody op 25-10-2005 21:52 . Reden: regeltje vergeten... ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Rhapsody schreef op dinsdag 25 oktober 2005 @ 21:50:
[...]

Ik heb jouw code fragment even vertaald naar VB.NET, maar ik lijk tegen precies hetzelfde aan te lopen:
Geeft hier geen problemen, een simple testje uitgevoerd maar is niet mis mee.

edit:
Visual Basic .NET:
1
RaiseEvent initcomplete(Me, Nothing)

Moet zijn:

Visual Basic .NET:
1
RaiseEvent initcomplete(Me, EventArgs.Empty)

[ Voor 23% gewijzigd door pjvandesande op 25-10-2005 21:54 ]


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
Hmm1: na het nogmaals testen laadt mijn tweede form niet
Hmm2: dan heb ik ergens een foutje gemaakt bij mijn conversie....

als ik een breakpoint zet op
Visual Basic .NET:
1
Debug.Assert(_frmDialog IsNot Nothing, "_frmDialog kan niet null zijn hier! Grr!")

in frmMain_InitComplete

dan blijkt dat ie daar niet eens naar toe gaat...

[ Voor 12% gewijzigd door Rhapsody op 25-10-2005 21:56 . Reden: Hmm1 toegevoegd. ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

En RaiseEvent initcomplete(Me, Nothing EventArgs.Empty) word wel aangeroepen?

[ Voor 16% gewijzigd door pjvandesande op 25-10-2005 22:03 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:36
Dan wil dat zeggen dat jouw event niet geraised wordt.
En ik denk dat dat ook best logisch is, aangezien je een method op een thread wilt uitvoeren die zich eigenlijk in een ander class bevindt.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

whoami schreef op dinsdag 25 oktober 2005 @ 22:01:
Dan wil dat zeggen dat jouw event niet geraised wordt.
En ik denk dat dat ook best logisch is, aangezien je een method op een thread wilt uitvoeren die zich eigenlijk in een ander class bevindt.
Hij zou dan in ieder geval wel moeten breaken op die breakpoint.

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
questa schreef op dinsdag 25 oktober 2005 @ 22:01:
En RaiseEvent initcomplete(Me, Nothing EventArgs.Empty) word wel aangeroepen?
die wordt wel uitgevoerd. Ik heb daar direct voor een messagebox staan, en die krijg ik ook gewoon te zien.
whoami schreef op dinsdag 25 oktober 2005 @ 22:01:
Dan wil dat zeggen dat jouw event niet geraised wordt.
En ik denk dat dat ook best logisch is, aangezien je een method op een thread wilt uitvoeren die zich eigenlijk in een ander class bevindt.
Dat zou inderdaad wel eens kunnen kloppen.

Als ik het event initcomplete als shared declareer, wordt deze wel correct opgevangen. Echter is het form dan een milliseconde te zien... :?

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Binnen je Load event gebeurt nu toch niets?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:36
Jouw form wordt geopend vanaf een andere thread (de thread waarop Init draait, raised nl. de InitComplete event). Daarna is de thread afgelopen, en is het ook logisch dat hij die form (die in die thread gemaakt werd), destroyed.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
questa schreef op dinsdag 25 oktober 2005 @ 22:07:
Binnen je Load event gebeurt nu toch niets?
Daar gebeurt nu niets.
Het is een simpel form met een calendarcontrol erop (enkel voor test)
whoami schreef op dinsdag 25 oktober 2005 @ 22:08:
Jouw form wordt geopend vanaf een andere thread (de thread waarop Init draait, raised nl. de InitComplete event). Daarna is de thread afgelopen, en is het ook logisch dat hij die form (die in die thread gemaakt werd), destroyed.
Aha, natuurlijk ja... stom

Dus wat ik nu het beste kan doen is op dat nieuwe form een thread starten en de data ophalen. Op die manier kan ik dan de gebruiker gewoon laten zien wat er gebeurt (dmv een progressbar bijvoorbeeld)

[ Voor 54% gewijzigd door Rhapsody op 25-10-2005 22:10 ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Rhapsody schreef op dinsdag 25 oktober 2005 @ 22:08:
[...]
Dus wat ik nu het beste kan doen is op dat nieuwe form een thread starten en de data ophalen. Op die manier kan ik dan de gebruiker gewoon laten zien wat er gebeurt (dmv een progressbar bijvoorbeeld)
Dit kun je gewoon oplossen door Invoke te gebruiken, dacht alleen dat het in VB.NET niet nodig was (ik tik nooit VB.NET) dus vandaar dat ik dit er eigelijk niet bijverteld heb maar je moet dus gewoon je event Invoken ipv zo RaiseEvent gebruiken. Mits noodzakelijk, in C# ziet het er iig zo uit:

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void OnInitComplete()
{
    If Not IniComplete Is Nothing Then
        Dim target As Control =  InitComplete.Target as Control 
 
        If target <> Nothing And target.InvokeRequired Then
            target.Invoke(InitComplete,New Object(){this,EventArgs.Empty)
        }
        else
        {
            InitComplete(this, Eventargs.Empty)
        }
        End If
    End If


edit:
De C#2VB converter maakt er niet echt iets moois van, maar je zou het wel begrijpen. Dus ipv RaiseEvent te gebruiken direct in je Init method, roep je nu de OnInitComplete method aan en deze zorgt voor een goede afhandeling.

[ Voor 13% gewijzigd door pjvandesande op 25-10-2005 22:21 ]


Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
Kun je de C# code eens plaatsen, ik kom niet helemaal uit die VB code

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Rhapsody schreef op dinsdag 25 oktober 2005 @ 22:44:
Kun je de C# code eens plaatsen, ik kom niet helemaal uit die VB code
Maar natuurlijk, moest er alleen even een nachtje over slapen :)
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected void OnInitComplete()
{
    if( InitComplete != null )
    {
        Control target = InitComplete.Target as Control;

        if( target != null && target.InvokeRequired )
        {
            // Invoked als het nodig is, dit houd in dat het Event op de
            // Main Thread wordt uitgevoerd.
            target.Invoke( InitComplete, new object[] {this, EventArgs.Empty} );
        }
        else
        {
            // Voert het Event uit op de huidige Thread.
            DescriptionChanged( this, EventArgs.Empty );
        }
    }
}

Acties:
  • 0 Henk 'm!

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 13:50

Rhapsody

In Metal We Trust

Topicstarter
Goedemorgen, en dank je wel! Ben nu weer op stage, dus ga er direct mee aan de slag.

edit:

die functie moet ik naar ik aanneem in het te openen form zetten he?
als in: dat is de functie die uitgevoerd dient te worden wanneer het event optreedt?

Ik krijg nu de volgende fout:
code:
1
Error   4   'Public Event initcomplete(sender As Object, e As System.EventArgs)' is an event, and cannot be called directly. Use a 'RaiseEvent' statement to raise an event.


En dat is op elke regel waar ik "initcomplete" heb staan.
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    Private Sub frmAbout_initcomplete(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.initcomplete
       If (initcomplete IsNot Nothing) Then  ' <--- HIER
            Dim target As Control
            target = initcomplete.Target' <--- HIER

            If (target IsNot Nothing And target.InvokeRequired) Then
                ' invoked als het nodig is dit houd in dat het Event op de 
                'Main Thread wordt uitgevoerd. 
                target.Invoke(initcomplete, New Object(), Me, EventArgs.Empty) ' <--- EN HIER
            Else
                ' Voert het Event uit op de huidige Thread. 
                RaiseEvent initcomplete(Me, EventArgs.Empty)
            End If
        End If
    End Sub


Edit:
Inmiddels ben ik weer wat verder. het enige waar ik nu nog mee zit is dat het formulier meteen weer gesloten wordt doordat, zoals Whoami al aangaf, het zich in een andere thread bevindt.
Edit 2:
Ik heb het zeer waarschijnlijk voor elkaar. Ik ga er nog ff mee spelen

[ Voor 106% gewijzigd door Rhapsody op 26-10-2005 11:10 ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


Acties:
  • 0 Henk 'm!

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 09-09 13:57

pjvandesande

GC.Collect(head);

Dit zou na een invoke opgelost moeten zijn. Alleen maar je volgens mij staat je hele code verkeerd. Binnen frmAbout_initcomplete, wat denk ik een event handler is ga je nogmaals een event omhoog gooien.

Zoals ik al eerder aangaf, je maakt een method binnen de class die jou Init event bevat namelijk een OnInitComplete (OnEventName).

Zodra jij het InitComplete event gefired wilt hebben roep je gewoon OnInitComplete aan, maar deze method protected zodat alleen binnen je class en overervers er gebruik van kunnen maken.

Visual Basic .NET:
1
target = initcomplete.Target

Kun je veranderen in:
Visual Basic .NET:
1
target = initcomplete.Target As Control

Hoewel dit kan in C#, ik weet niet of dit ook in VB werkt. De As operator zou initcomplete.Target moeten casten naar een Control, lukt dit niet dan krijg je geen exception maar gewoon een null (Nothing in VB.NET) waarde terug.
Pagina: 1