[C#]Thread 1e keer stoppen duurt 670 ms. Daarna 0 ms

Pagina: 1
Acties:

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:37
Hoi,

Ben me nu eindelijk eens aan het verdiepen in het threading etc. etc.

Nu wil ik een thread stoppen met onderstaande code:
C#:
1
2
3
4
5
6
7
8
9
private void StopThread()
{
    AddMessageToTextBox("Stopping thread");
    m_WorkerThreadMethod.Interrupt();
    m_WorkerThreadMethod.Abort();
    m_WorkerThreadMethod.Join();
    AddMessageToTextBox(Environment.NewLine+"Stopped");
    m_WorkerThreadMethod = null;
}


Tijdens het debuggen / runnen van de applicatie is me opgevallen dat de allereerste keer na de build het stoppen van de thread 670 ms duurt, vervolgens alle keren daarop 0 ms.

Ik heb het project al eens van Debug naar release gezet, maar dat maakt geen verschil.

Heart..pumps blood.Has nothing to do with emotion! Bored


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

Heb je in de thread method nog een finally statement waar dinge netjes afgehandeld worden die wat tijd in beslag nemen?

  • Alex
  • Registratie: Juli 2001
  • Laatst online: 08-02 12:48
Bovenstaande code zegt een beetje weinig. Je kunt inprinciepe een 2e keer een stopcommando op een nog bestaande thread aanroepen. Deze staat dan nog in een soort van stille modus zonder datiie gedisposed is. Laat eens ff wat meer code zien, zou ik zeggen :)

Deze post is bestemd voor hen die een tegenwoordige tijd kunnen onderscheiden van een toekomstige halfvoorwaardelijke bepaalde subinverte plagiale aanvoegend intentioneel verleden tijd.
- Giphart


  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:37
De code uit de WorkerThread.cs:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void GetFiles()
{
    string FilePath = @"D:\Inetpub\images\storage\";
    System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(FilePath);
    int i = 1;
    foreach(System.IO.FileInfo file in dir.GetFiles("*.jpg"))
    {
        _uiform.Invoke(
            _uiform.m_DelegateAddString,
            new object[]
            {"File " +i+": "+ file.Name.ToString()+Environment.NewLine}
        );
        i++;
        Thread.Sleep(100);
    }
}
questa schreef op maandag 31 juli 2006 @ 21:38:
Heb je in de thread method nog een finally statement waar dinge netjes afgehandeld worden die wat tijd in beslag nemen?
Nope. :)
Alex de Groot schreef op maandag 31 juli 2006 @ 21:58:
Bovenstaande code zegt een beetje weinig. Je kunt inprinciepe een 2e keer een stopcommando op een nog bestaande thread aanroepen. Deze staat dan nog in een soort van stille modus zonder datiie gedisposed is. Laat eens ff wat meer code zien, zou ik zeggen :)
Ik hoop dat ik nu wel voldoende code heb laten zien.

Bovenstaande code is losjes gebaseerd op een tutorial van CodeProject waarbij ik een aantal zaken eruit laat (bijv. ManualResetEvent etc.)

De originele code was in eerste instantie:
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
// Stop worker thread if it is running.
// Called when user presses Stop button of form is closed.
private void StopThread()
{
    if ( m_WorkerThread != null  &&  m_WorkerThread.IsAlive )  // thread is active
    {
    // set event "Stop"
    m_EventStopThread.Set();

        // wait when thread  will stop or finish
        while (m_WorkerThread.IsAlive)
        {
            // We cannot use here infinite wait because our thread
            // makes syncronous calls to main form, this will cause deadlock.
            // Instead of this we wait for event some appropriate time
            // (and by the way give time to worker thread) and
            // process events. These events may contain Invoke calls.
            if ( WaitHandle.WaitAll(
                (new ManualResetEvent[] {m_EventThreadStopped}), 
                100,
                true) )
            {
                break;
            }

            Application.DoEvents();
        }
    }
}

Nu heb ik gelezen/gehoord/begrepen dat .DoEvents() zoveel mogelijk vermeden moest worden dus bovenstaande code eruit gelaten.

Heart..pumps blood.Has nothing to do with emotion! Bored


  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Een aantal vragen:

- Welke versie van .NET hebben we het over?
- Heb je al eens met een profiler gekeken? Het zou namelijk heel goed kunnen dat bepaalde code of assemblies in je StopThread of onderliggende onderdelen moet worden ge-inlined omdat het eerder nog niet gebruikt is.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 12-02 12:22
Niks ergs, is gewoon een stukje IL code die naar native gecompileerd wordt. Daardoor is het na de eerste keer een stuk sneller.

1 van de belangrijkste zaken bij performance testen van .NET, Java en elke andere VM gebaseerde taal, het zijn net diesel motoren. Pas als ze even gedraaid hebben komen ze tot hun maximale rendement.

Aangezien meestal een thread aan zijn einde komt door normaal uit zijn run methode te returnen is het aannemelijk dat de code die je gebruikt om de betreffende thread te killen nog nooit aangeroepen is in je huidige life cycle.

[ Voor 25% gewijzigd door The - DDD op 01-08-2006 09:17 ]


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Ik heb niet veel ervaring met C#, maar dit klinkt idd. als een optimalisatie (oid) die een enkele keer wordt uitgevoerd. Dat is iig het eerste waar ik aan dacht.

Noushka's Magnificent Dream | Unity


  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:37
Dat mag :)
- Welke versie van .NET hebben we het over?
1.1
- Heb je al eens met een profiler gekeken? Het zou namelijk heel goed kunnen dat bepaalde code of assemblies in je StopThread of onderliggende onderdelen moet worden ge-inlined omdat het eerder nog niet gebruikt is.
Nee, maar ik zal dat eens doen inderdaad. Wat bedoel je met ge-inlined?
The - DDD schreef op dinsdag 01 augustus 2006 @ 09:15:
Niks ergs, is gewoon een stukje IL code die naar native gecompileerd wordt. Daardoor is het na de eerste keer een stuk sneller.
Zou je denken? Heb je daar ook enig 'bewijs' van?
1 van de belangrijkste zaken bij performance testen van .NET, Java en elke andere VM gebaseerde taal, het zijn net diesel motoren. Pas als ze even gedraaid hebben komen ze tot hun maximale rendement.

Aangezien meestal een thread aan zijn einde komt door normaal uit zijn run methode te returnen is het aannemelijk dat de code die je gebruikt om de betreffende thread te killen nog nooit aangeroepen is in je huidige life cycle.
Opzich wel een plausibele theorie. Bedankt, zal er eens verder in duiken.
Michali schreef op dinsdag 01 augustus 2006 @ 09:17:
Ik heb niet veel ervaring met C#, maar dit klinkt idd. als een optimalisatie (oid) die een enkele keer wordt uitgevoerd. Dat is iig het eerste waar ik aan dacht.
Het e.e.a. begint me ook wel een beetje te dagen.

Nogmaals, ik zal er nog eens met een profiler overheen wandelen.

Heart..pumps blood.Has nothing to do with emotion! Bored


  • Sybr_E-N
  • Registratie: December 2001
  • Nu online
TeeDee schreef op dinsdag 01 augustus 2006 @ 10:57:
Zou je denken? Heb je daar ook enig 'bewijs' van?
Het is de JIT compiler die er de eerste keer tussen zit. Bewijs? Zo werkt .NET nou eenmaal, voor meer uitleg moet je even de MSDN checken. Daar wordt precies uitgelegd wat dat inhoudt, zelfde geld voor inlinen.

.NET compileert de source code eerst naar een tussenvorm, op het moment dat de code voor het eerst wordt uitgevoerd wordt er x86 code van gemaakt. Na de eerste keer wordt dat laaste dus gebruikt.

Als je gaat zoeken op JIT kom je al een stuke verder, als je de grap erachter wilt weten.

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:37
Sybr_E-N schreef op dinsdag 01 augustus 2006 @ 12:17:
[...]

Het is de JIT compiler die er de eerste keer tussen zit.
Aha! Zal inderdaad eens kijken wat de JIT nu exact wil doen. :)
Bewijs? Zo werkt .NET nou eenmaal, voor meer uitleg moet je even de MSDN checken. Daar wordt precies uitgelegd wat dat inhoudt, zelfde geld voor inlinen.
Met bewijs doel ik meer op een bron. Als ik niet weet dat dit te maken heeft met JIT, dan wordt het vrij lastig om daarop te zoeken. Inlinen zal ik even opzoeken.
.NET compileert de source code eerst naar een tussenvorm, op het moment dat de code voor het eerst wordt uitgevoerd wordt er x86 code van gemaakt. Na de eerste keer wordt dat laaste dus gebruikt.
Bedankt voor de uitleg. Ik dacht dat de IL gecompileerd werd, vervolgens de x86 en dan pas runnen.
Als je gaat zoeken op JIT kom je al een stuke verder, als je de grap erachter wilt weten.
Of ik de grap wil weten, weet ik niet, maar het kan zeker geen kwaad om er eens in te duiken.

Heart..pumps blood.Has nothing to do with emotion! Bored


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 12-02 12:22
TeeDee schreef op dinsdag 01 augustus 2006 @ 15:18:
Met bewijs doel ik meer op een bron. Als ik niet weet dat dit te maken heeft met JIT, dan wordt het vrij lastig om daarop te zoeken. Inlinen zal ik even opzoeken.
Voor zover ik IL van .NET ken wordt de code geinterpreteerd. Stuken code die aan bepaalde voorwaarden voldoen worden echter als "hot spot" aangeduidt en naar native code overgezet. Dit gebeurt eigenlijk altijd runtime.

Bron: Ervaringsdeskundig met Java en in de .NET 1.0 tijd er ook is mee bezig geweest. :+

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

TeeDee schreef op dinsdag 01 augustus 2006 @ 15:18:
[...]

Met bewijs doel ik meer op een bron. Als ik niet weet dat dit te maken heeft met JIT, dan wordt het vrij lastig om daarop te zoeken. Inlinen zal ik even opzoeken.
NGEN de boel gewoon even? Ben je daar iig vanaf.

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:37
NGEN ken ik niet, ziet er op zich wel netjes uit, alleen zijn er (als ik het zo her en der lees) wel wat nadelen aan.

Maar goed, zoals ik al in de TS zei is dit een oefenproject om Threading etc. onder de knie te krijgen.
De 'release' (als je hiervan kan spreken) doet het gelukkig al een stuk beter. De eerste stap wordt namelijk terug gebracht naar 46 ms.

Ik heb weer wat leesvoer en ben gelukkig weer een aantal dingen te weten gekomen.

Bedankt allen.

Heart..pumps blood.Has nothing to do with emotion! Bored


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

TeeDee schreef op dinsdag 01 augustus 2006 @ 16:38:
NGEN ken ik niet, ziet er op zich wel netjes uit, alleen zijn er (als ik het zo her en der lees) wel wat nadelen aan.

Maar goed, zoals ik al in de TS zei is dit een oefenproject om Threading etc. onder de knie te krijgen.
De 'release' (als je hiervan kan spreken) doet het gelukkig al een stuk beter. De eerste stap wordt namelijk terug gebracht naar 46 ms.

Ik heb weer wat leesvoer en ben gelukkig weer een aantal dingen te weten gekomen.

Bedankt allen.
Je zou NGEN kunnen gebruiken om te kijken of het aan de JIT ligt dat de code zolang duur de eerste keer.
Pagina: 1