Results 1 to 14 of 14

Thread: voor en tegens plaatsen in thread

  1. #1
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747

    voor en tegens plaatsen in thread

    Ik vind het altijd lastig om te bepalen welke processen nu in een aparte thread moeten werken.
    Situatie als volgt:

    Er komt een partij goederen binnen. Deze worden gekeurd en ontvangen. Daarna wordt deze partij via webservices aangeboden. Deze webservice heeft eigen codes van de geleverde producten. De productcode moet dus eerst worden omgezet. Dan heb ik twee scenario's:

    1. De conversie tabellen worden in het begin al geladen (via een class). Er wordt opgezocht welke code correspondeert met de webservice. Deze code wordt dan meegegeven in de aparte thread. In die thread wordt dan een record aangemaakt. Doordat de tabel in het begin al is geladen, kan er snel worden gezocht. Nadeel is wel dat die tabel niet wordt ververst als er een aanpassing is geweest (al gebeurt dat niet vaak en kan ik een signaal sturen dat er een refresh moet worden uitgevoerd). Dat zoeken (en e.v.t. laden van de tabellen voor de eerste keer) gebeurt in de mainthread, waardoor de gebruiker moet wachten totdat de thread wordt uitgevoerd.

    2. De conversie tabellen worden in de aparte thread geladen Er wordt opgezocht welke code correspondeert met de webservice. In die thread wordt dan een record aangemaakt. Alles wordt in de achtergrond uitgevoerd, maar de conversie tabellen worden wel elke keer opgehaald, omdat deze ook weer verdwijnt nadat de thread is vrijgegeven. Maar de gebruiker merkt daar helemaal niets van.

    Maar welke situatie is nu het meest voordeligst?
    Delphi is great. Lazarus is more powerfull

  2. #2
    Lokaal data van een webserice opslaan is over het algemeen geen goed idee. Maar waarom een thread, één record aanmaken zal toch niet langer dan 0.1 seconde duren?
    Marcel

  3. #3
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Het niet zozeer het aanmaken van de record, maar het openen van de webservice, de gegevens doorsturen, wachten op antwoord, antwoord opslaan in de huidige database. Het versturen en wachten kost het meeste tijd.

    Maar gaande weg (een wandeling in het bos) ben ik er wel uit. Ik heb beschikking over een SQL database en kan dus een query aanmaken met de gegevens, die ik wil. Vandaar uit kan ik alles opzoeken wat ik wil. Ik ga de hele procedure verwerken vanuit een aparte thread.
    Delphi is great. Lazarus is more powerfull

  4. #4
    Die wandelingen ken ik . Even afstand nemen van je probleem is altijd zinvol, dat levert vaak creatieve oplossingen op.
    Marcel

  5. #5
    Senior Member Thaddy's Avatar
    Join Date
    Dec 2004
    Location
    Amsterdam
    Posts
    2,211
    Tja Marcel.

    (je weet mijn achtergrond)

    Als je het aan je personeel kunt laten vertrouwen dan kun je dat best in een thread doen.
    Maar voor de rest geldt natuurlijk je goede opleiding in parallellisatie van algoritmes en die bestaan al bijna voor eeuwig. (Weliswaar niet in computerwetenschappen, maar ik stuitte nog vrij onlangs op een Grieks stukje parrallel universum)
    Werken aan Ansi support voor Windows is verspilde tijd, behalve voor historici.

  6. #6
    Ik snap in dit verhaal het issue niet echt waarom dit in een thread zou moeten.

    Ook geeft John veel te weinig info over het probleem om er iets zinnigs over te zeggen. Een batch proces (wat dit voor mij gevoelsmatig is) in een thread laten lopen is op zich een optie, maar ik vraag me af of het nodig is. Als je niet als basis al een degelijk framework hebt staan geven threads meer ellende dan ze oplossen en ze zijn vaak ook nog veel lastiger te debuggen / verifieren.

    @John, je hebt een kbmMW licentie. Steek je tijd in het leren van kbmMW en ga het framework gebruiken. Dat levert je uiteindelijk veel meer winst op dan nu weer zelf gaan knutselen met threads en alle ellende die daarbij komt kijken.

  7. #7
    Jan
    Join Date
    Oct 2007
    Location
    Mijdrecht
    Posts
    906
    In .net moet je alles in threads doen. Een button op disabled zetten en dan een actie doen die iets langer duurt werkt niet. Pas na het uitvoeren van de actie staat de button op disabled. Bijna alles wat je doet blokkeert de UI.
    Helaas zijn er in .net vier verschillende manieren om met asynchroon programmeren om te gaan en voor iedere methode zijn weer talloze 'patterns'.
    Dan is Delphi threading toch wel echt simpel.

  8. #8
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Ik heb nu de proces in een thread staan. Laat deze maar lekker de gegevens ophalen vanuit een webservice. De gebruiker kan verder met zijn werk, omdat deze geen gebruik maakt van de terugkoppeling.
    Delphi is great. Lazarus is more powerfull

  9. #9
    Mij viel meer deze opmerking op
    De conversie tabellen worden in de aparte thread geladen Er wordt opgezocht welke code correspondeert met de webservice. In die thread wordt dan een record aangemaakt. Alles wordt in de achtergrond uitgevoerd, maar de conversie tabellen worden wel elke keer opgehaald, omdat deze ook weer verdwijnt nadat de thread is vrijgegeven.
    Als de thread meerdere keren gebruikt kan worden is het "duurder" om deze voor elke actie opnieuw aan te maken en ook de links naar de database opnieuw op te bouwen dan om de thread 1 keer te maken en alleen in actie te laten komen als er weer een object is die verwerkt dient te worden. Soort van consumer-producer model.

  10. #10
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    hoe start ik een thread in de achtergrond, die maar 1 keer geladen hoeft te worden, maar meerdere keren kan worden uitgevoerd?
    Delphi is great. Lazarus is more powerfull

  11. #11
    De thread start altijd in de achtergrond daar hoef je niet verder niets aan te doen. Om hem maar 1 keer te starten en daarna meerdere keren te gebruiken doe je meestal het makkelijkst door het werk niet direct aan de thread aan te bieden maar aan een queue en de thread de inhoud van de queue te laten verwerken.

    Er zijn vrij veel verschillende technieken. Eea hangt af van hoe je de data aan wilt/kunt bieden aan de thread. Een makkelijke gebaseerd op de message queue is
    Code:
    ...
    const
         WM_REQUEST = WM_USER + 1;
         WM_INFORM = WM_USER + 4;
    ...
       PWerkRec = ^AWerkRec;
       AWerkRec = record
          A  : String;
          B : String;
          C  : Integer;
       End;
    
    ...
         PostThreadMessage(Consumer.ThreadID, WM_REQUEST, 0, Integer(WerkRec));
    ...
    procedure TConsumerThread.Execute;
    var
       Msg: TagMsg;
       Werk : PWerkRec;
    begin
         ... make alle database componenten aan...
         while (GetMessage(Msg, 0, 0, 0)) and (not terminated) do
         begin
            Case Msg.message of
               WM_REQUEST    : Begin
                                   Werk := PWerk(Msg.LParam);
                                   .. do wat met het werk...
                               End;
               WM_INFORM     : Begin
                                   .. do wat anders
                               end;
            else
               Begin
                  TranslateMessage(Msg);
                  DispatchMessage(Msg);
               end
            end;
         end;
    end;

  12. #12
    Jan
    Join Date
    Oct 2007
    Location
    Mijdrecht
    Posts
    906
    Hoeveel milliseconden bespaar je met deze techniek ? En als dat dan toch belangrijk is, zou ik de omnithread library gebruiken :
    http://www.omnithreadlibrary.com/

  13. #13
    Quote Originally Posted by mesa57 View Post
    Hoeveel milliseconden bespaar je met deze techniek ?
    Geen idee, als je eerst bijv een lekkere database verbinding moet opbouwen, daarna met een sappige sql de records moet ophalen en daarna eea besluiten voordat het weer weggeschreven wordt en dat dan een paar honderd keer per werkdag dan loopt de besparing wel op.

    Maar de hint hoeveel 1000de ms het bespaart stond in de OP "...Dat zoeken (en e.v.t. laden van de tabellen voor de eerste keer) gebeurt in de mainthread, waardoor de gebruiker moet wachten .." Lijkt mij dat pas bij seconden en niet millisec's er spraken is van wachten De techniek is ook niet altijd bedoelt om de performance te verbeteren maar ook vaak om de UI niet te blokkeren door de data async te verwerken.

    Zelf gebruik ik meerdere producers en meerdere consumers, de consumers zijn weer in een waterval model opgebouwd om de data verder te verrijken . Op die manier worden gigabytes aan data verwerkt zonder dat de main UI hoe dan ook geblokkeerd is.

  14. #14
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Ik heb een constructie als Miep maar dan meer Delphi dan winapi. Dus met TEvent.Waitfor enz.

    Een eigen post routine zet het event (een record met een type, een paar object refs integers en reals in een queue (generics.collections dacht ik) en signaled de event die triggert.

    De simpelste event is dan iets als

    Delphi Code:
    1. case arecord.eventype of
    2.  
    3.       execobject : TExeobject(arecord.objectref).execute(arecord);
    4.    end;

    TExeobject is simpelweg een tobject met een virtual execute met het record als var parameter. Dat maakt dat je voor veel klein grut de thread unit kan recyclen zonder steeds nieuwe gevallen aan de ifdef toe te voegen.

    Wel ff goed opletten dat je event.resetevent op de goede plek staat.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •