[c#] Timer in een thread die log moet updaten

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Candanz
  • Registratie: Februari 2013
  • Laatst online: 19-08-2024
Hallo, mede-tweakers en programmeurs

Ik ben momenteel bezig met een programmatje voor een groepje vrienden, die graag een web-scraper willen hebben die alle images downloaden. Nu is het downloaden en het scannen van de site an-sich geen probleem, maar het moet meerdere sites tegelijk scannen, en hiervan dus de images ook opslaan.

Nu wil ik het nog mooi hebben dat je ook daadwerkelijk text te zien krijgt als hij de website gescanned heeft, en nieuwe plaatjes heeft gevonden.

Nu loop ik alleen tegen een probleem aan:

1. In de "Scanner/Downloader" thread word een timer aangemaakt met een interval van 1000 * de refresh rate die door de gebruiker is ingevuld. Hierop heb ik een tick event geadd.

2. Het tick event wordt uitgevoerd, maar stuurt pas data terug zodra hij klaar is. Ik zou dit graag zo willen hebben dat data direct wordt verzonden naar de UI thread, maar heb dus geen idee hoe.

M'n timer, gevolgd door m'n functie die de timer set. gevolgd door de functie die als tick event wordt uitgevoerd.
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
public System.Timers.Timer t;

private void initLoad()
        {
            main.updateLog("Loaded: "+Thread.CurrentThread.Name+"\n");

            t = new System.Timers.Timer();

            t.Elapsed += new ElapsedEventHandler(scanForImages);

            t.Interval = 1000*iRefresh;

            t.Enabled = true;
        }



        public void scanForImages(object s, ElapsedEventArgs e)
        {

            if (status != 1 && status != 4)
            {
                status = 1;
                int i = 0;
                while (status == 1)
                {
                    main.updateLog(th.Name + ": Blaat\n");
                    i++;
                    if (i > 50)
                    {
                        status = 4;
                        t.Stop();
                        main.updateThreads("Aborting: " + th.Name, th);

                        th.Abort();
                    }
                }
            }
            else
            {
                t.Stop();
            }
        }


Vervolgens zijn hier mijn functies updateLog en updateThreads:

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
public void updateThreads(string s, Thread t)
        {
            if (t.ThreadState.ToString() != "Aborted" && t.ThreadState.ToString() != "Stopped")
            {
                if (data.Any(item => item.Val == t.Name))
                {
                    listThreads lst = data.Where<listThreads>(x => x.Val == t.Name).Single<listThreads>();

                    lst.Text = s;
                }
                else
                {
                    data.Add(new listThreads() { Text = s, Val = t.Name, Worker = t });
                }
            }
            else
            {
                listThreads lst = data.Where<listThreads>(x => x.Val == t.Name).Single<listThreads>();

                data.Remove(lst);
            }

            string update = "Thread: " + t.Name + " "+t.ThreadState.ToString()+"\n";

            if (InvokeRequired)
            {
                Action action = () => updateLog(update);
                action.Invoke();
            }
            else
            {
                updateLog(update);
            }
            
        }

public void updateLog(string txt)
        {

            if (InvokeRequired)
            {
                Action action = () => textBox2.AppendText(txt);
                textBox2.Invoke(action);
            }
            else
            {
                textBox2.AppendText(txt);
            }
           
        }


Het werkt allemaal naar behoren, maar alleen de timer geeft dus een probleem, dat hij de data "cached" als het ware, en de data pas verstuurt nadat de timer klaar is. Het is niet zo dat de UI "ge-locked" is, want ik kan gewoon nieuwe url's inladen en in de log typen.

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 12-07 22:24
Candanz schreef op zondag 31 maart 2013 @ 08:25:
Het werkt allemaal naar behoren, maar alleen de timer geeft dus een probleem, dat hij de data "cached" als het ware, en de data pas verstuurt nadat de timer klaar is. Het is niet zo dat de UI "ge-locked" is, want ik kan gewoon nieuwe url's inladen en in de log typen.
Je hebt nou eenmaal een periodiek moment gekozen waar je de threads synchroniseert; met zo'n strategie ga je dit effect altijd hebben. Als je dat niet wilt, laat de threads dan gewoon 'vrij' en gebruik een thread-safe collectie type zoals ConcurrentQueue om je log boodschappen en updates tussen de threads te versturen.

Overigens; er is tegenwoordig een heel fijne Task<T> class voor asynchrone acties. Direct tegen die vreselijk onoverzichtelijke Thread API aanpraten is niet meer van deze tijd.

Acties:
  • 0 Henk 'm!

  • king_charles
  • Registratie: Maart 2008
  • Laatst online: 15-08-2023
R4gnax schreef op zondag 31 maart 2013 @ 12:31:
[...]
Overigens; er is tegenwoordig een heel fijne Task<T> class voor asynchrone acties. Direct tegen die vreselijk onoverzichtelijke Thread API aanpraten is niet meer van deze tijd.
Periodiciteit is niet echt het sterkste punt van Tasks. Hiervoor gebruik ik toch echt nog Timers.

Acties:
  • 0 Henk 'm!

  • Candanz
  • Registratie: Februari 2013
  • Laatst online: 19-08-2024
R4gnax schreef op zondag 31 maart 2013 @ 12:31:
[...]


Je hebt nou eenmaal een periodiek moment gekozen waar je de threads synchroniseert; met zo'n strategie ga je dit effect altijd hebben. Als je dat niet wilt, laat de threads dan gewoon 'vrij' en gebruik een thread-safe collectie type zoals ConcurrentQueue om je log boodschappen en updates tussen de threads te versturen.
Ik snap nog niet zo heel veel van threads e/d. Maar dank voor je post, ik zal hier verder na kijken.
Overigens; er is tegenwoordig een heel fijne Task<T> class voor asynchrone acties. Direct tegen die vreselijk onoverzichtelijke Thread API aanpraten is niet meer van deze tijd.
Ik zal hier ook maar eens naar kijken.