Vra

Ek het probeer om multi-threaded programmering in C# te leer en ek is verward oor wanneer dit die beste is om 'n thread pool te gebruik vs.skep my eie drade.Een boek beveel aan om 'n draadpoel slegs vir klein take te gebruik (wat dit ook al beteken), maar ek kan blykbaar geen regte riglyne vind nie.Wat is 'n paar oorwegings wat jy gebruik wanneer jy hierdie programmeringsbesluit neem?

Was dit nuttig?

Oplossing

As jy baie logiese take het wat konstante verwerking vereis en jy wil hê dit moet parallel gedoen word, gebruik die swembad+skeduleerder.

As jy jou IO-verwante take gelyktydig moet maak, soos om goed van afgeleë bedieners af of skyftoegang af te laai, maar dit moet sê een keer elke paar minute, maak dan jou eie drade en maak hulle dood sodra jy klaar is.

Wysig:Oor sommige oorwegings gebruik ek draadpoele vir databasistoegang, fisika/simulasie, AI (speletjies), en vir geskrewe take wat op virtuele masjiene uitgevoer word wat baie gebruikergedefinieerde take verwerk.

Normaalweg bestaan ​​'n poel uit 2 drade per verwerker (so waarskynlik 4 deesdae), maar jy kan die hoeveelheid drade wat jy wil opstel, as jy weet hoeveel jy nodig het.

Wysig:Die rede om jou eie drade te maak is as gevolg van konteksveranderinge, (dit is wanneer drade in en uit die proses moet ruil, saam met hul geheue).Om nuttelose konteksveranderinge te hê, sê wanneer jy nie jou drade gebruik nie, om hulle net te laat sit soos mens kan sê, kan maklik die helfte van die werkverrigting van jou program hê (sê jy het 3 slapende drade en 2 aktiewe drade).As die aflaai-drade dus net wag, eet hulle tonne SVE op en koel die kas af vir jou regte toepassing

Ander wenke

Ek stel voor jy gebruik 'n draad poel in C # vir dieselfde redes as enige ander taal.

As jy wil hê dat die aantal drade loop beperk of wil nie die oorhoofse van die skep en hulle vernietig, gebruik 'n draad poel.

Deur klein take, die boek wat jy lees beteken take met 'n kort leeftyd. As dit neem tien sekondes om 'n draad wat net loop vir 'n sekonde te skep, dit is 'n plek waar jy moet die gebruik van swembaddens (ignoreer my werklike syfers, dit is die verhouding wat tel).

Andersins kan jy die grootste deel van jou tyd spandeer skep en te vernietig drade eerder as om net te doen die werk wat hulle bedoel is om te doen.

Hier is 'n lekker opsomming van die draad swembad in Net: http://blogs.msdn.com/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx

Die post het ook 'n paar punte op wanneer jy nie moet gebruik maak van die draad swembad en begin jou eie draad plaas.

Ek hoogs lees die hierdie gratis e-boek aanbeveel: Threading in C # deur Joseph Albahari

Ten minste lees die artikel "Aan die slag". Die e-boek bied 'n groot inleiding en sluit 'n rykdom van gevorderde threading inligting sowel.

Om te weet of te gebruik die draad swembad is net die begin. Volgende wat jy nodig het om te bepaal watter metode van toetrede tot die draad swembad beste by jou behoeftes:

  • Taak Parallel Biblioteek (NET Framework 4.0)
  • ThreadPool.QueueUserWorkItem
  • Asynchronous Afgevaardigdes
  • Background

Hierdie e-boek verduidelik hulle almal en beveel toe om dit te gebruik teen jou eie draad.

Die draadpoel is ontwerp om kontekswisseling tussen jou drade te verminder.Oorweeg 'n proses wat verskeie komponente aan die gang het.Elkeen van daardie komponente kan werkersdrade skep.Hoe meer drade in jou proses is, hoe meer tyd word vermors op kontekswisseling.

Nou, as elkeen van daardie komponente items in die tou in die draadpoel geplaas het, sou jy baie minder konteks oorskakeling hê.

Die draadpoel is ontwerp om die werk wat oor jou SVE's (of SVE-kerns) gedoen word, te maksimeer.Daarom draai die draadpoel by verstek verskeie drade per verwerker op.

Daar is 'n paar situasies waar jy nie die draadpoel wil gebruik nie.As jy wag op I/O, of wag op 'n gebeurtenis, ens., dan bind jy daardie draadpoeldraad vas en dit kan nie deur iemand anders gebruik word nie.Dieselfde idee is van toepassing op langlopende take, alhoewel wat 'n langlopende taak uitmaak subjektief is.

Pax Diablo maak ook 'n goeie punt.Om drade op te draai is nie gratis nie.Dit neem tyd en hulle verbruik bykomende geheue vir hul stapelspasie.Die draadpoel sal drade hergebruik om hierdie koste te amortiseer.

Let wel:jy het gevra oor die gebruik van 'n draadpoeldraad om data af te laai of skyf-I/O uit te voer.U moet nie 'n draadpoeldraad hiervoor gebruik nie (vir die redes wat ek hierbo uiteengesit het).Gebruik eerder asynchrone I/O (ook bekend as die BeginXX- en EndXX-metodes).Vir 'n FileStream dit sal wees BeginRead en EndRead.Vir 'n HttpWebRequest dit sal wees BeginGetResponse en EndGetResponse.Hulle is meer ingewikkeld om te gebruik, maar dit is die regte manier om multi-threaded I/O uit te voer.

Pasop vir die NET draad swembad vir operasies wat kan sluit vir enige beduidende, veranderlike of onbekende deel van hul verwerking, want dit is geneig om honger ryg. Oorweeg die gebruik van die NET parallel uitbreidings, wat 'n goeie aantal van logiese abstraksies te verskaf oor gestruktureerde bedrywighede. Dit sluit ook 'n nuwe skeduleerder, wat 'n verbetering op ThreadPool moet wees. Sien hier

Een van die redes vir die gebruik van die draad poel vir klein take is net dat daar 'n beperkte aantal draad swembad drade. As 'n mens gebruik vir 'n lang tyd dan tot stilstand kom dit dat draad van wat gebruik word deur ander kode. As dit gebeur baie keer dan die draad swembad kan raak opgebruik.

Die gebruik van die draad swembad kan subtiele effekte -. N paar NET timers gebruik draad swembad drade en sal nie afgegaan, byvoorbeeld

As jy 'n agtergrond taak wat sal lewe vir 'n lang tyd, soos vir die hele leeftyd van jou aansoek, dan skep jou eie draad is 'n redelike ding. As jy 'n kort werk wat gedoen moet word in 'n draad, gebruik dan draad poel.

In 'n aansoek waar jy is die skep van baie drade, die oorhoofse van die skep van die drade word aansienlike. Die gebruik van die draad swembad skep die drade eens en hergebruik hulle daardeur die draad skepping oorhoofse.

In 'n program wat ek gewerk het op, die verandering van die skep van gesprekke wat tot die gebruik van die draad swembad vir die korte duur drade regtig helpped die deur sit van die aansoek.

Vir die hoogste werkverrigting met gelyktydige uitvoering van eenhede, skryf jou eie draadpoel, waar 'n poel Thread-voorwerpe geskep word by aanvang en gaan na blokkering (voorheen opgeskort), en wag op 'n konteks om te hardloop ('n voorwerp met 'n standaardkoppelvlak wat geïmplementeer word deur jou kode).

Soveel artikels oor Take vs.Drade vs.die .NET ThreadPool gee nie regtig wat jy nodig het om 'n besluit vir prestasie te neem nie.Maar as jy dit vergelyk, wen Threads en veral 'n poel Threads.Hulle word die beste oor SVE's versprei en hulle begin vinniger.

Wat bespreek moet word, is die feit dat die hoofuitvoeringseenheid van Windows (insluitend Windows 10) 'n draad is, en OS-konteksskakeling oorhoofse koste is gewoonlik weglaatbaar.Eenvoudig gestel, ek kon nie oortuigende bewyse van baie van hierdie artikels vind nie, of die artikel hoër werkverrigting beweer deur kontekswisseling of beter SVE-gebruik te bespaar.

Nou vir 'n bietjie realisme:

Die meeste van ons sal nie ons toepassing nodig hê om deterministies te wees nie, en die meeste van ons het nie 'n harde agtergrond met drade nie, wat byvoorbeeld dikwels kom met die ontwikkeling van 'n bedryfstelsel.Wat ek hierbo geskryf het, is nie vir 'n beginner nie.

Wat dus die belangrikste is om te bespreek, is wat maklik is om te programmeer.

As jy jou eie draadpoel skep, sal jy 'n bietjie skryfwerk hê om te doen, aangesien jy bekommerd moet wees oor die opsporing van uitvoeringstatus, hoe om opskorting en hervat te simuleer, en hoe om uitvoering te kanselleer - insluitend in 'n toepassing-wye sluit af.Jy moet dalk ook bekommerd wees oor of jy jou swembad dinamies wil laat groei en ook watter kapasiteitsbeperking jou swembad sal hê.Ek kan so 'n raamwerk in 'n uur skryf, maar dit is omdat ek dit soveel keer gedoen het.

Miskien is die maklikste manier om 'n uitvoeringseenheid te skryf om 'n taak te gebruik.Die skoonheid van 'n taak is dat jy een kan skep en dit in lyn in jou kode kan afskop (hoewel versigtigheid geregverdig kan word).Jy kan 'n kansellasietoken deurgee om te hanteer wanneer jy die taak wil kanselleer.Dit gebruik ook die beloftebenadering om gebeure te ketting, en jy kan dit 'n spesifieke soort waarde laat teruggee.Boonop bestaan ​​daar meer opsies met async en wag, en u kode sal meer draagbaar wees.

In wese is dit belangrik om die voor- en nadele met Take vs.Drade vs.die .NET ThreadPool.As ek hoë werkverrigting benodig, gaan ek drade gebruik, en ek verkies om my eie swembad te gebruik.

'n Maklike manier om te vergelyk, is om 512 Threads, 512 Tasks en 512 ThreadPool-drade te begin.Jy sal 'n vertraging in die begin vind met Threads (dus hoekom skryf 'n thread pool), maar al 512 Threads sal binne 'n paar sekondes loop terwyl Take en .NET ThreadPool drade tot 'n paar minute neem om almal te begin.

Hieronder is die resultate van so 'n toets (i5 quad core met 16 GB RAM), wat elke 30 sekondes gee om te hardloop.Die kode wat uitgevoer word, voer eenvoudige lêer I/O op 'n SSD-aandrywer uit.

Toets resultate

Thread swembaddens is groot wanneer jy meer take te verwerk as beskikbaar drade.

Jy kan al die take te voeg om 'n draad swembad en spesifiseer die maksimum aantal drade wat kan loop op 'n sekere tyd.

Kyk bietjie na hierdie bladsy op MSDN : http://msdn.microsoft.com/en-us /library/3dasc8as(VS.80).aspx

Gebruik altyd 'n draad poel as jy kan, werk op die hoogste vlak van abstraksie moontlik. Draad poele verberg skep en te vernietig drade vir jou, dit is gewoonlik 'n goeie ding!

Die meeste van die tyd wat jy kan die swembad gebruik as jy die duur proses van die skep van die draad vermy.

Maar in sommige scenarios kan jy 'n draad te skep. Byvoorbeeld, as jy is nie die enigste een met behulp van die draad swembad en die draad wat jy maak is langlewende (om te verhoed dat die verbruik van gedeelde hulpbronne) of byvoorbeeld as jy wil hê dat die stacksize van die draad te beheer.

Moenie vergeet om die agtergrond werker ondersoek.

Ek vind vir 'n baie situasies, dit gee my net wat ek wil sonder die swaar werk.

Cheers.

Ek gewoonlik die Threadpool gebruik wanneer ek nodig het om net iets op 'n ander draad te doen en het nie regtig omgee wanneer dit loop of eindig. Iets soos te meld of miskien selfs agtergrond 'n lêer af te laai (alhoewel daar is beter maniere om dit asinkroniseer-styl doen). Ek gebruik my eie draad toe ek meer beheer nodig. Ook wat ek gevind word met behulp van 'n Threadsafe tou (hack jou eie) na "command voorwerpe" stoor is lekker as ek het verskeie opdragte wat ek nodig het om op te werk in> 1 draad. So jy wil kan verdeel 'n XML-lêer en sit elke element in 'n tou en dan verskeie drade besig besig met 'n verwerking van hierdie elemente. Ek het so 'n tou pad terug in uni (VB.net!) Wat ek tot bekering te C #. Ek het dit ingesluit hieronder vir geen spesifieke rede (hierdie kode kan 'n paar foute bevat).

using System.Collections.Generic;
using System.Threading;

namespace ThreadSafeQueue {
    public class ThreadSafeQueue<T> {
        private Queue<T> _queue;

        public ThreadSafeQueue() {
            _queue = new Queue<T>();
        }

        public void EnqueueSafe(T item) {
            lock ( this ) {
                _queue.Enqueue(item);
                if ( _queue.Count >= 1 )
                    Monitor.Pulse(this);
            }
        }

        public T DequeueSafe() {
            lock ( this ) {
                while ( _queue.Count <= 0 )
                    Monitor.Wait(this);

                return this.DeEnqueueUnblock();

            }
        }

        private T DeEnqueueUnblock() {
            return _queue.Dequeue();
        }
    }
}

Ek wou 'n draad poel te werk oor kern versprei met so min latency as moontlik, en dit het nie te goed speel met ander programme. Ek het gevind dat die NET draad swembad prestasie was nie so goed soos dit kon wees. Ek het geweet ek wou een draad per kern, so ek het my eie draad swembad plaasvervanger klas. Die kode word as 'n antwoord op 'n ander StackOverflow vraag hier .

As die oorspronklike vraag, die draad swembad is nuttig vir die oortreding van herhalende berekeninge in dele wat in parallel uitgevoer kan word (as hulle kan uitgevoer word in parallel sonder om die uitkoms). Handleiding draad bestuur is nuttig vir take soos UI en IO.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top