[C#] Events aanmaken in Threads

Pagina: 1
Acties:

  • Av3ng3rtje
  • Registratie: December 2002
  • Laatst online: 05-01 22:08
Ik ben bezig met een programma wat om de zoveel tijd gestart wordt een paar xml feeds inleest, kijkt of er wat nieuws en dat download naar me schijf.

Nu wil ik via een thread de downloads laten verlopen en de progressbar (standaard form component) updaten. Nu moet je daar voor invoken begreep ik.

Wat nu niet lukt is het aanmaken van events in threads. Als ik probeer de debuggen kom in de lus in en daarna kan ik niet meer zien wat er gebeurd... De progressbar wordt ook niet geupdate. Ik heb het ook al met een gewoon label geprobeerd en dat wou ook al niet werken.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
delegate void CallbackUpdateProgressDownload(int progress);

private void frmMain_Load(object sender, EventArgs e
{
    //start een nieuwe thread
    Thread thread = new Thread(new ThreadStart(Download));

    thread.Start();
}


private void Download()
{
    //maak enumerator aan
    Dictionary<string, Mod>.Enumerator enumerator = mod.Mods.GetEnumerator();

    //door loop de collectie
    while (enumerator.MoveNext())
    {
        //nieuw webclient object
            WebClient client = new WebClient();

        //event er hangen, kan dit zo?
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);

        //bestand downloaden aan de hand van een waarde in de collectie
            client.DownloadFile(enumerator.Current.Value.DownloadUrl, directory + "/download/" + enumerator.Current.Value.BuildName + ".zip");

    }
}

private void updateProgress(int progress)
{
    progressDownload.Value = progress;
}

//event
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    //kijk of hij geinvoked moet worden
    if (progressDownload.InvokeRequired)
    {
        //zoja delegeer hem door
        CallbackUpdateProgressDownload callback = new CallbackUpdateProgressDownload(updateProgress);
    }
    else
    {
        //anders update hem
        updateProgress(e.ProgressPercentage);
    }
}

  • MichelVH
  • Registratie: Oktober 2001
  • Laatst online: 15-10-2025
Je vergeet je delegate te invoken:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
{ 
    //kijk of hij geinvoked moet worden 
    if (progressDownload.InvokeRequired) 
    { 
        //zoja delegeer hem door 
        Invoke(new CallbackUpdateProgressDownload(upgradeProgress), new object[] { e.ProgressPercentage }); 
    } 
    else 
    { 
        //anders update hem 
        updateProgress(e.ProgressPercentage); 
    } 

[ Voor 6% gewijzigd door MichelVH op 04-05-2006 00:14 ]

Don't be afraid of the dark, be afraid of what it hides


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:33
Maak een aparte class die de taak bevat die op een andere thread moet draaien:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class TheTask
{

      public event EventHandler SomethingOccured;

      protected void OnSomethingOccured()
      {
           if( SomethingOccured != null )
           {
                 Windows.Forms.Control c = SomethingOccured.Target as System.Windows.Forms.Control;

                 if( c != null && c.InvokeRequired )
                 {
                        c.Invoke ( ... );
                 }
                 else
                 {
                         SomethingOccured ( .. )
                 }
           }
      }

    public void Run()
    {
         Thread t = new ThreadStart (workermethod);
          t.Start();
    }

    private void workermethod()
    {
          ....
    }

}


De bovenstaande code is niet compleet, maar het zou je wel een idee moeten geven.
(Het is eigenlijk ook beter om de invocation-list van de event op te vragen, en voor iedere delegatge in de invocation list apart te kijken of die moet ge-invoked worden of niet.
Als je gebruik maakt van .NET 2.0 kan je ook gebruik maken van de background-worker thread ipv zelf een class te schrijven.

https://fgheysels.github.io/


  • Av3ng3rtje
  • Registratie: December 2002
  • Laatst online: 05-01 22:08
Ik heb de oplossing van Michel met een label geprobeerd met een gewone functie in de while lus met een delegate. Deze werkt wel, alleen het is nu zo dat hij het event niet pakt ( client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged); ) in de while loop die in de thread zit, net alsof de eventhandler van client niet buiten zijn thread kan treden om een functie uit te voeren..

[ Voor 140% gewijzigd door Av3ng3rtje op 04-05-2006 13:39 ]


  • st0p
  • Registratie: April 2004
  • Laatst online: 19-07-2024
[lichtelijk off-topic]
ik ben niet zo thuis in threading, maar is het aanroepen van events in andere threads niet behoorlijk riskant?

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 20-02 14:52

gorgi_19

Kruimeltjes zijn weer op :9

st0p schreef op donderdag 04 mei 2006 @ 11:20:
[lichtelijk off-topic]
ik ben niet zo thuis in threading, maar is het aanroepen van events in andere threads niet behoorlijk riskant?
Hoezo? :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • Av3ng3rtje
  • Registratie: December 2002
  • Laatst online: 05-01 22:08
Wat werkt wel:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
delegate void CallBackUpdateProgressLabel(string update);

//De workermethod
private void Download()
{
    Dictionary<string, Mod>.Enumerator enumerator = mod.Mods.GetEnumerator();

    while (enumerator.MoveNext())
    {
    threadUpdateLabel(enumerator.Current.Value.Name);
    }
}

private void threadUpdateLabel(string msg)
{
    if (lblProgressStatus.InvokeRequired)
    {
    lblProgressStatus.Invoke(new CallBackUpdateProgressLabel(updateLabel), new object[] { msg });
    }
    else
    {
    updateLabel(msg);
    }
}

private void updateLabel(string msg)
{
    lblProgressStatus.Text = msg;
}


Wat werkt niet:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
delegate void CallbackUpdateProgressDownload(DownloadProgressChangedEventArgs progress);

//De workermethod
private void Download()
{
    Dictionary<string, Mod>.Enumerator enumerator = mod.Mods.GetEnumerator();

    while (enumerator.MoveNext())
    {
    WebClient client = new WebClient();
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
    client.DownloadFile(enumerator.Current.Value.DownloadUrl, directory + "/download/" + enumerator.Current.Value.BuildName + ".zip");
    }
}

void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    if (progressDownload.InvokeRequired)
    {
    progressDownload.Invoke(new CallbackUpdateProgressDownload(updateProgress), new object[] { e });
    }
    else
    {
    updateProgress(e);
    }
}


private void updateProgress(DownloadProgressChangedEventArgs progress)
{
    progressDownload.Value = progress.ProgressPercentage;
}
Pagina: 1