Code uitvoeren NA het laden van een form

Status
Niet open voor verdere reacties.

pdedecker

Gebruiker
Lid geworden
19 jul 2008
Berichten
35
Momenteel is dit mijn frmNewsticker_load:
Code:
        private void frmNewsticker_Load(object sender, EventArgs e)
        {
            UpdateHeadlines();
            GetNewHeadline();
        }
UpdateHeadlines moet een RSS-feed van het internet downloaden, dus het is niet zo handig dat het formulier verborgen blijft totdat het feed geladen is. Beter zou ik vinden dat het formulier al verschijnt en dat ik een boodschap in de aard van "Bezig met laden..." erop kon zetten. Is het mogelijk om bepaalde functies uit te voeren na het laden van het formulier? Of, nog beter, is het mogelijk om een functie aan te roepen en onmiddellijk door te gaan met het script terwijl die functie zijn werk doet?
 
Ik heb het volgende gevonden en het codevoorbeeld eens bekeken.

Ik doe dus:
Code:
    public partial class frmNewsticker : Form
    {
        // andere declaraties stonden hier
        private Thread GetStoryThread = new Thread(new ThreadStart(GetStory));
        // hier staan wat methodes
    }

De methode die aangeroepen wordt door de Thread is private void GetStory, een onderdeel van frmNewsticker. Vervolgens krijg ik deze foutmelding van de debugger: A field initializer cannot reference the non-static field, method, or property 'NewsTicker.frmNewsticker.GetStory()' . In het codevoorbeeld wordt verwezen naar void DisplayThread1() en void DisplayThread2(), beiden geen statische methodes. Het kan dus niet zijn dat ik GetStory statisch moet maken zoals de foutmelding mij doet vermoeden. Wat is er wel fout?
 
Laatst bewerkt:
Hey,

het is makkelijker om met een BackgroundWorker te werken.
Dit is ook een andere thread. Deze kun je gewoon starten in de Form_Load().
Dat wordt het scherm weergegeven, en de thread is dan nogsteeds aan het laden van de gegevens. En zo heb je dus die status..

Als de gegevens opgehaald zijn, kun je deze laten laden in de BackgroundWorker_Completed. In deze event kunnen gegevens geladen worden in het formulier.

Ik hoop dat je er iets mee kunt.

Succes,
Mathijs
 
Dus dààr dient BackgroundWorker voor! Het is eigenlijk een beetje dom, maar ik heb ongeveer 65% van "Visual C# 2008: De basis" uitgelezen en kon niet wachten om te beginnen. De naam BackgroundWorker had ik al in een volgend hoofdstuk zien staan waar ik nog niet aan toe was. Ik kan dat beter zo snel mogelijk uitlezen voordat ik nog domme vragen stel... :o

(In de tussentijd gebruik ik een Timer die een heel lage interval heeft.)
 
Laatst bewerkt:
Aan de hand van een C#-boek heb ik een BackgroundWorker proberen op te zetten.

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace Televised
{
    public partial class frmTelevised : Form
    {
        // instructies...
        private BackgroundWorker fetcher = new BackgroundWorker();
    // methodes...
    private void frmTelevised_Load(object sender, EventArgs e)
        {
            fetcher.WorkerReportsProgress = true;
            fetcher.WorkerSupportsCancellation = false;
            fetcher.DoWork += new DoWorkEventHandler(DataUpdater);
            fetcher.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SetUpdateTimer);
        }
    // methodes...
    private void DataUpdater(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker fetcher = sender as BackgroundWorker;
            // instructies...
        }
    private void SetUpdateTimer(object sender, RunWorkerCompletedEventArgs e)
        {
            // instructies...
        }
    // methodes...
    }
}

Dit werkt niet bij mij. Het werk dat de BackgroundWorker moet doen, gebeurt niet. Mis ik een instructie?
 
Ja, dat mis je zeker ;)
fetcher.RunWorkerAsync();
Je start de background worker niet...
Dit moet wel in de Form_Load().

En trouwens:
Code:
 private void DataUpdater(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker fetcher = sender as BackgroundWorker;
            // instructies...
        }
werkt niet. Want fetcher is al gedeclareerd in de klasse.
Die regel mag helemaal ontbreken, want dat heb je niet nodig.

Gr,
Mathijs
 
Oh, leuk... Ik probeer een labeltje te wijzigen vanuit de methode die door de BackgroundWorker aangeroepen wordt en ik krijg het bericht dat ik geen thread-safe calls doe. Kan het kwaad om vanuit die methode een label te wijzigen dat nooit door andere programmaonderdelen gewijzigd wordt? De workaround die ik hiervoor moet doen klinkt mij wat ingewikkeld.
 
Hey,

in de RunWorker_Completed kun je wel een label updaten. Dus als het updaten voltooid is, dan kun je dat daar in de label aangeven.
Als je tussendoor de label wilt aanpassen zijn er meedere manieren.
De 1e had je zelf al gevonden. Het lijkt ingewikkeld, maar het is werkelijk maar ongeveer 6 regels code om dat te laten werken.

Een 2e die ik gebruik, is de background worker in combimatie met een timer.
De Backgroundworker laat ik het zware rekenwerk doen. Dan laat ik een bepaalde status in een variabele zetten. Dan laat in een timer om de 0,5 seconde de label updaten met de waarde van de variabele.
Die manier werkt perfect :thumb:

Succes,
Mathijs
 
Kan ik ook parameters doorgeven aan een Thread?

Code:
this.ControlUpdater1 = new Thread(new ThreadStart(this.SetText("parameter1", "parameter2")));
geeft Method name expected.
 
Aan een gewone thread?
Dat weet ik zo niet.
Maar aan een backgroundworker gaat dat wel.
Moet je gewoon RunWorkerAsync(parameter) uitvoeren.

Dan kun je in de methode van de backgroundworker de parameter opvragen met de DoWorkEventArgs. (e.Parameter)

ALs je meerdere wilt mee sturen, dan moet je een object[] maken. En daar alle parameters in zetten. Die kun je dan weer mee sturen met de backgroundworker.

Ik hoop dat het zo duidelijk is.

Succes,
Mathijs
 
Pfft, die thread safety heeft toch meer voeten in aarde dan ik dacht. Ik moet echt parameters door kunnen geven aan die thread.

Wat kan er in theorie misgaan als ik thread-unsafe calls toelaat voor Labels, PictureBoxes en ProgressBars die alleen door dezelfde BackgroundWorker worden gewijzigd? Die BackgroundWorker wordt trouwens elke minuut doorlopen, maar normaal gezien duurt de uitvoering ervan maar tien seconden.
 
Nou, ik heb een oplossing voor je...
Deze oplossing voer je uit in de nieuwe thread. Die thread stuurt dan een signaal naar de andere, en zo wordt de label geupdate

Code:
delegate void UpdateStatusDelegate(string value);
private void UpdateStatus(string text)
{
    if (InvokeRequired)
        BeginInvoke(new UpdateStatusDelegate(UpdateStatus), new object[] { text });
    else
        label1.Text = text;
}

Succes,
Mathijs
 
Hmm... dat werpt nog een probleempje op. Kan ik dit universeel laten werken (m.a.w. dat ik de naam van het label en de inhoud van het label doorgeef)? label1.Text = text; is nog makkelijk te herschrijven, maar met BeginInvoke(new UpdateStatusDelegate(UpdateStatus), new object[] { text }); weet ik geen raad.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan