.NET: Zvishandiso zvekushanda nemultithreading uye asynchrony. Chikamu 1

Ndiri kuburitsa chinyorwa chepakutanga paHabr, dudziro yacho yakatumirwa mukambani blog.

Iko kudikanwa kwekuita chimwe chinhu asynchronously, pasina kumirira mhedzisiro pano uye ikozvino, kana kupatsanura basa rakakura pakati pemayuniti akati wandei arikuita, yaivepo pamberi pekuuya kwemakomputa. Nekuuya kwavo, ichi chinodikanwa chakava chinobatika kwazvo. Iye zvino, muna 2019, ndiri kunyora chinyorwa ichi palaptop ine 8-core Intel Core processor, pane anopfuura zana maitiro ari kushanda akafanana, uye kunyange tambo dzakawanda. Pedyo, pane nharembozha shoma, yakatengwa makore akati wandei apfuura, ine 8-core processor pabhodhi. Thematic zviwanikwa zvakazara nezvinyorwa uye mavhidhiyo uko vanyori vazvo vanoyemura gore rino mureza mafoni ane gumi nematanhatu-core processors. MS Azure inopa muchina chaiwo une 16 core processor uye 20 TB RAM isingasviki $128/awa. Nehurombo, hazvibviri kubvisa iyo yakanyanya uye kubatanidza simba iri pasina kukwanisa kubata kupindirana kwetambo.

Terminology

Process - OS chinhu, yakasarudzika kero nzvimbo, ine tambo.
Thread - chinhu cheOS, diki diki yekuuraya, chikamu chemaitiro, tambo dzinogovana ndangariro uye zvimwe zviwanikwa pakati pavo mukati mekuita.
Kuita zvakawanda - OS pfuma, kugona kumhanya akati wandei maitiro panguva imwe chete
Multi-core - chivakwa che processor, kugona kushandisa akati wandei macores ekugadzirisa data
Multiprocessing - pfuma yekombuta, kugona kushanda panguva imwe chete nevakawanda processors mumuviri
Multithreading - chivakwa chemaitiro, kugona kugovera kugadzirisa data pakati petambo dzinoverengeka.
Parallelism - kuita zviito zvakati wandei panguva imwe chete pachikamu chenguva
Asynchrony -Kuitwa kwekuvhiya pasina kumirira kupera kwekugadziriswa uku; mhedzisiro yekuuraya inogona kugadziriswa gare gare.

Metaphor

Hadzisi dzese tsananguro dzakanaka uye dzimwe dzinoda imwe tsananguro, saka ini ndichawedzera dimikira pamusoro pekubika kudya kwemangwanani kune iyo yakaunzwa zviri pamutemo izwi. Kubika kudya kwemangwanani mudimikira iri ibasa.

Ndichigadzira kudya kwemangwanani mangwanani ini (CPU) ndinouya kukitchen (Komputa) Ndine maoko maviri (cores) Kune akati wandei emidziyo mukicheni (IO): ovheni, kettle, toaster, firiji. Ini ndinobatidza gasi, ndoisa pani yekubikira ndodira mafuta mairi ndisina kumirira kuti kupisa (asynchronously, Non-Blocking-IO-Mirira), ndinotora mazai kubva mufiriji ndokuapwanya mundiro, ndozoarova neruoko rumwe (Thread#1), uye chechipiri (Thread#2) akabata ndiro (Shared Resource). Zvino ndinoda kubatidza ketero, asi handina maoko akakwana (Thread Nzara) Munguva iyi, pani inopisa inopisa (Kugadzirisa chigumisiro) iyo yandinodurura zvandakarova. Ndinosvika pagate ndobatidza ndoona nekupusa mvura ichivira mairi (Kuvhara-IO-Mirira), kunyange zvazvo panguva iyi angadai akasuka ndiro yaakarova omelet.

Ndakabika omelette ndichishandisa maoko maviri chete, uye ini handina zvimwe, asi panguva imwe chete, panguva yekurova omelet, mavhisi matatu akaitika kamwechete: kurova omelet, kubata ndiro, kupisa pani. .CPU ndiyo inokurumidza chikamu chekombuta, IO ndiyo inowanzoita kuti zvinhu zvese zvinonoke, saka kazhinji mhinduro inoshanda ndeyekugadzika CPU nechimwe chinhu uchigamuchira data kubva kuIO.

Kuenderera mberi nedimikira:

  • Kana ndiri mukugadzirira omelet, ndaizoedzawo kuchinja zvipfeko, izvi zvingava muenzaniso we multitasking. Chinhu chakakosha nuance: makomputa ari nani pane izvi kupfuura vanhu.
  • Ikicheni ine vabiki vanoverengeka, semuenzaniso muresitorendi - komputa yakawanda-yakakosha.
  • Mazhinji maresitorendi munzvimbo yekudya mune imwe nzvimbo yekutengesa - data center

.NET Tools

.NET yakanaka pakushanda neshinda, sezvimwe zvinhu zvakawanda. Neyega yega vhezheni itsva, inounza mamwe maturusi matsva ekushanda nawo, mitsva mitsva yekubvisa pamusoro peOS tambo. Paunenge uchishanda nekuvaka kwekubvisa, vanogadzira framework vanoshandisa nzira inosiya mukana, kana uchishandisa yakakwirira-level abstraction, kuenda pasi imwe kana mamwe mazinga pazasi. Kazhinji kazhinji izvi hazvidikanwi, chaizvoizvo zvinovhura musuwo wekupfura iwe pachako mutsoka nepfuti, asi dzimwe nguva, muzviitiko zvisingawanzoitiki, inogona kunge iri iyo nzira chete yekugadzirisa dambudziko risina kugadziriswa pamwero wezvino wekubvisa. .

Nezvishandiso, ndinoreva zvese zviri zviviri application programming interfaces (APIs) inopihwa neiyo furemu uye yechitatu-bato mapakeji, pamwe nesese software mhinduro dzinorerutsa kutsvaga kwechero matambudziko ane chekuita nekodhi-yakawanda.

Kutanga shinda

The Thread class ndiyo yakanyanya kukosha kirasi mu.NET yekushanda neshinda. Mugadziri anogamuchira mumwe wevamiriri vaviri:

  • ThreadStart - Hapana paramita
  • ParametrizedThreadStart - ine imwe parameter yemhando chinhu.

Nhume ichaitwa mushinda ichangobva kugadzirwa mushure mekudaidza nzira yeKutanga Kana nhume yerudzi rweParametrizedThreadStart yakatambidzwa kumugadziri, ipapo chinhu chinofanira kupfuudzwa kunzira yeKutanga. Iyi nzira inodiwa kuendesa chero ruzivo rwemunharaunda kune rukova. Zvakakosha kucherechedza kuti kugadzira shinda ibasa rinodhura, uye shinda pachayo chinhu chinorema, zvirinani nekuti inogovera 1MB yekuyeuka pane stack uye inoda kudyidzana neOS API.

new Thread(...).Start(...);

The ThreadPool kirasi inomiririra pfungwa yedziva. MuNET, dziva reshinda ichidimbu cheinjiniya, uye vagadziri veMicrosoft vakaisa simba rakawanda mukuona kuti inoshanda zvakakwana mumhando dzakasiyana siyana.

General concept:

Kubva panguva iyo application yatanga, inogadzira akati wandei akachengetwa kumashure uye inopa kugona kuitora kuti ishandiswe. Kana tambo dzichishandiswa kakawanda uye muhuwandu hukuru, dziva rinowedzera kuti rizadzise zvinodiwa neanofona. Kana pasina tambo dzemahara mudziva panguva yakakodzera, inomirira kuti imwe yeshinda idzoke, kana kugadzira imwe nyowani. Izvi zvinotevera kuti dziva reshinda rakanaka kune zvimwe zviitwa zvenguva pfupi uye zvisina kukodzera maoperation anomhanya semasevhisi mukati mese kushanda kwechikumbiro.

Kushandisa shinda kubva padziva, pane nzira yeQueueUserWorkItem inogamuchira nhume yerudzi rweWaitCallback, ine siginicha yakafanana neParametrizedThreadStart, uye parameter inopfuudzwa kwairi inoita basa rimwe chete.

ThreadPool.QueueUserWorkItem(...);

Iyo isingazivikanwe tambo dziva nzira RegisterWaitForSingleObject inoshandiswa kuronga isiri-kuvharira IO mashandiro. Nhume yakapfuudzwa kune iyi nzira ichadaidzwa kana WaitHandle yapfuura kune iyo nzira "Yakaburitswa".

ThreadPool.RegisterWaitForSingleObject(...)

.NET ine thread timer uye inosiyana neWinForms/WPF timers pakuti mubati wayo achadaidzwa pashinda yakatorwa mudziva.

System.Threading.Timer

Kune zvakare imwe nzira yakasarudzika yekutumira mumiriri kuti aurawe kune shinda kubva padziva - iyo BeginInvoke nzira.

DelegateInstance.BeginInvoke

Ndinoda kugara muchidimbu pamusoro pebasa iro nzira dzakawanda dziri pamusoro dzinogona kunzi - CreateThread kubva kuKernel32.dll Win32 API. Pane nzira, nekuda kwemaitiro ekunze nzira, kudaidza basa iri. Ndakaona kudaidzwa kwakadaro kamwe chete mumuenzaniso unotyisa wekodhi yenhaka, uye kurudziro yemunyori akaita izvi chaizvo ichiri chakavanzika kwandiri.

Kernel32.dll CreateThread

Kuona uye Debugging Threads

Mathreads akagadzirwa newe, ese echitatu-party components, uye .NET pool inogona kuonekwa muThreads window yeVisual Studio. Iri hwindo rinongoratidza ruzivo rwetambo kana application iri pasi pedebug uye muBreak mode. Pano iwe unogona kuona zviri nyore mazita ezvituki uye zvinokosheswa zveshinda yega yega, uye chinja kugadzirisa kune imwe shinda. Uchishandisa iyo Yekutanga pfuma yeThread kirasi, unogona kuseta kukosha kwetambo, iyo iyo OC neCLR inozoona sekurudziro kana uchipatsanura processor nguva pakati peshinda.

.NET: Zvishandiso zvekushanda nemultithreading uye asynchrony. Chikamu 1

Basa Parallel Library

Task Parallel Library (TPL) yakaunzwa mu.NET 4.0. Iye zvino ndiyo yakajairwa uye chishandiso chikuru chekushanda neasynchrony. Chero kodhi inoshandisa nzira yekare inoonekwa senhaka. Chinhu chakakosha cheTPL iTask class kubva kuSystem.Threading.Tasks namespace. Basa (task) kureva chidimbu pamusoro peshinda. Neiyo vhezheni itsva yemutauro weC #, takawana nzira inoyevedza yekushanda neMatask - async/kumirira vanoshanda. Idzi pfungwa dzakaita kuti zvikwanise kunyora asynchronous kodhi sekunge iri nyore uye inopindirana, izvi zvakaita kuti zvikwanise kunyange kune vanhu vane nzwisiso shoma yekushanda kwemukati kwetambo kunyora maapplication anoashandisa, maapplication asingaome kana achiita maoperation akareba. Kushandisa async/kumirira inyaya yechinyorwa chimwe kana akati wandei, asi ini ndichaedza kuwana pfungwa yacho mumitsara mishoma:

  • async inogadziridza nzira yekudzosera Basa kana kushaya
  • uye kumirira ndeye isingavharidzi Task yakamirira opareta.

Zvekare: anomirira opareta, mune yakajairika kesi (kune zvisizvo), achaburitsa yazvino tambo yekuuraya mberi, uye kana Task yapedza kuurayiwa kwayo, uye shinda (chaizvoizvo, zvingave zvakanyanya kutaura mamiriro acho ezvinhu. , asi zvimwe pane izvozvo gare gare) ichaenderera mberi nekuita nzira yacho mberi. Mukati meNET, nzira iyi inoshandiswa nenzira imwecheteyo sekudzoka kwegoho, apo nzira yakanyorwa inoshanduka kuita kirasi yose, iyo iri muchina wehurumende uye inogona kuurayiwa muzvidimbu zvakasiyana zvichienderana nematunhu aya. Chero ani zvake anofarira anogona kunyora chero akareruka kodhi achishandisa asynс/kumirira, kuunganidza uye kuona gungano uchishandisa JetBrains dotPeek ine Compiler Generated Code inogoneswa.

Ngatitarisei sarudzo dzekutanga uye kushandisa Task. Mumuenzaniso wekodhi pazasi, tinogadzira basa idzva risingaiti chinhu chinobatsira (Thread.Kurara(10000)), asi muhupenyu chaihwo iyi inofanira kunge iri imwe yakaoma CPU-inoshanda basa.

using TCO = System.Threading.Tasks.TaskCreationOptions;

public static async void VoidAsyncMethod() {
    var cancellationSource = new CancellationTokenSource();

    await Task.Factory.StartNew(
        // Code of action will be executed on other context
        () => Thread.Sleep(10000),
        cancellationSource.Token,
        TCO.LongRunning | TCO.AttachedToParent | TCO.PreferFairness,
        scheduler
    );

    //  Code after await will be executed on captured context
}

Basa rinogadzirwa nehuwandu hwesarudzo:

  • LongRunning chiratidzo chekuti basa harizopedzwe nekukurumidza, izvo zvinoreva kuti zvingave zvakakosha kufunga kusatora shinda kubva padziva, asi kugadzira yakaparadzana yeBasa iri kuitira kuti isakuvadza vamwe.
  • AttachedToParent - Mabasa anogona kurongwa mune hierarchy. Kana iyi sarudzo yakashandiswa, saka Basa rinogona kunge riri munzvimbo iyo pacharo rakapedza uye rakamirira kuurayiwa kwevana varo.
  • PreferFairness - zvinoreva kuti zvingave nani kuita Mabasa akatumirwa kuurayiwa kare vasati vatumirwa gare gare. Asi iyi ingori kurudziro uye mhedzisiro haina kuvimbiswa.

Yechipiri paramende yakapfuudzwa kune iyo nzira ndeye CancellationToken. Kuti ubate nemazvo kukanzura oparesheni mushure mekunge yatanga, kodhi iri kuitwa inofanirwa kuzadzwa necheki yeCancellationToken state. Kana pasina cheki, ipapo nzira yeKanzura inodaidzwa paCancellationTokenSource chinhu ichakwanisa kumisa kuitwa kweTask chete isati yatanga.

Iyo yekupedzisira parameter chinhu chechirongwa cherudzi rweTaskScheduler. Kirasi iyi nevazukuru vayo vakagadzirirwa kudzora marongero ekugovera Mabasa mukati meshinda; nekusarudzika, Basa rinozoitwa pane imwe tambo kubva padziva.

Mushandi wekumirira anoshandiswa kune Task yakagadzirwa, zvinoreva kuti kodhi yakanyorwa shure kwayo, kana iripo, ichaitwa mumamiriro ezvinhu akafanana (kazhinji izvi zvinoreva pane imwechete thread) sekodhi isati yamirira.

Iyo nzira yakanyorwa seasync void, zvinoreva kuti inogona kushandisa akamirira opareta, asi iyo yekufona kodhi haizokwanisa kumirira kuurayiwa. Kana chimiro chakadaro chichidikanwa, ipapo nzira yacho inofanira kudzorera Basa. Nzira dzakamakwa async void dzakajairika: sekutonga, idzi vabati vezviitiko kana dzimwe nzira dzinoshanda pamoto uye kukanganwa musimboti. Kana iwe usingadi kwete chete kupa mukana wekumirira kusvika pakuguma kwekuurayiwa, asiwo kudzorera chigumisiro, saka unoda kushandisa Task.

Pamusoro peTask iyo nzira yeStartNew yakadzoka, pamwe nechero ipi zvayo, unogona kudana nzira yeConfigureAwait neparameter yenhema, ipapo kuurayiwa mushure mekumirira kunoenderera mberi kwete pane zvakabatwa, asi pane imwe chete. Izvi zvinofanirwa kuitwa nguva dzose kana mamiriro ekuuraya asina kukosha kune kodhi mushure mekumirira. Uku zvakare kurudziro kubva kuMS kana uchinyora kodhi iyo inounzwa yakarongedzwa muraibhurari.

Ngatitaurei zvishoma pamusoro pekuti ungamirira sei kupedzwa kweBasa. Pazasi pane muenzaniso wekodhi, ine zvirevo pamusoro pekuti tarisiro inoitwa riinhi zvakanaka uye kana ichiitwa zvisina kunaka.

public static async void AnotherMethod() {

    int result = await AsyncMethod(); // good

    result = AsyncMethod().Result; // bad

    AsyncMethod().Wait(); // bad

    IEnumerable<Task> tasks = new Task[] {
        AsyncMethod(), OtherAsyncMethod()
    };

    await Task.WhenAll(tasks); // good
    await Task.WhenAny(tasks); // good

    Task.WaitAll(tasks.ToArray()); // bad
}

Mumuenzaniso wekutanga, tinomirira kuti Basa ripedze pasina kuvharira tambo yekufona; isu tichadzokera kugadzirisa mhedzisiro chete kana yatovepo; kusvika ipapo, tambo yekufona inosiiwa kune yayo yega.

Muchisarudzo chechipiri, tinovhara tambo yekudana kusvikira mugumisiro wenzira yaverengwa. Izvi hazvina kunaka kwete chete nekuti isu takagara tambo, yakakosha sosi yechirongwa, nekusashanda kuri nyore, asiwo nekuti kana iyo kodhi yenzira yatinodaidza yakamirira, uye mamiriro ekuenderana anoda kudzokera kune yekufona tambo mushure. mirira, tobva tawana zvakafa : Tambo yekufona inomirira kuti mhedzisiro yeasynchronous nzira iverengerwe, iyo asynchronous nzira inoedza pasina kuenderera mberi nekuita kwayo mutambo yekufona.

Chimwe chinokanganisa nzira iyi yakaoma kubata kukanganisa. Icho chokwadi ndechekuti zvikanganiso muasynchronous kodhi kana uchishandisa async / wakamirira zviri nyore kubata - vanoita zvakafanana sekunge kodhi yaienderana. Nepo kana tikashandisa synchronous kumirira exorcism kuTask, iyo yekutanga yakasarudzika inoshanduka kuita AggregateException, i.e. Kuti ubate iyo yakasarudzika, iwe uchafanirwa kuongorora iyo InnerException mhando uye nyora kana cheni iwe pachako mukati meimwe yekubata block kana kushandisa hove kana uchivaka, pachinzvimbo chetani yezvivharo zvekubata izvo zvinozivikanwa munyika yeC #.

Muenzaniso wechitatu uye wekupedzisira wakanyorwawo wakashata nechikonzero chimwe chete uye une matambudziko akafanana.

Iyo WhenAny uye WhenAll nzira dzakanyanya nyore kumirira boka reMabasa; vanoputira boka reMabasa mune rimwe, iro rinopisa kana Basa kubva muboka rikatanga kubatwa, kana kana vese vapedza kuuraya kwavo.

Kumisa tambo

Nezvikonzero zvakasiyana-siyana, zvingave zvakakosha kumisa kuyerera mushure mekunge kwatanga. Pane nzira dzakawanda dzekuita izvi. Iyo Thread kirasi ine maviri akakodzera mazita nzira: Kubvisa ΠΈ Kanganisa. Yekutanga haina kukurudzirwa kushandiswa, nekuti mushure mekudaidzira chero nguva isingaite, panguva yekugadziriswa kwechero rairo, kusarudzika kunokandwa ThreadAbortedException. Iwe hautarisire kusarudzika kwakadaro kukandwa paunenge uchiwedzera chero nhamba inosiyana, handiti? Uye kana uchishandisa nzira iyi, iyi ndiyo mamiriro chaiwo chaiwo. Kana iwe uchida kudzivirira iyo CLR kubva pakugadzira yakasarudzika mune imwe chikamu chekodhi, unogona kuiputira mumafoni. Thread.BeginCriticalRegion, Thread.EndCriticalRegion. Chero kodhi yakanyorwa muvharovha yekupedzisira yakaputirwa mumafoni akadai. Nechikonzero ichi, mukati memukati meiyo kodhi yekodhi iwe unogona kuwana zvidhinha nekuedza kusina chinhu, asi kwete chisina chinhu pakupedzisira. Microsoft inoodza moyo nzira iyi zvekuti havana kuisanganisira mu.net core.

Iyo Interrupt nzira inoshanda zvakanyanya kufanofungidzira. Inogona kukanganisa shinda kunze ThreadInterruptedException chete panguva idzodzo apo shinda inenge yakamirira. Inopinda munzvimbo iyi ichirembera ichimirira WaitHandle, kukiya, kana mushure mekufonera Thread.Kurara.

Zvose zviri zviviri sarudzo dzakatsanangurwa pamusoro dzakaipa nekuda kwekusaziva kwavo. Mhinduro ndeyokushandisa chimiro CancellationToken uye kirasi CancellationTokenSource. Pfungwa ndeiyi: muenzaniso weCancellationTokenSource kirasi inogadzirwa uye iye chete muridzi wayo anogona kumisa kushanda nekudaidza nzira. kanzura. Chete CancellationToken inopfuudzwa kuoperation pachayo. Varidzi veCancellationToken havagone kudzima oparesheni ivo pachavo, asi vanogona kungotarisa kana oparesheni yakadzimwa. Pane Boolean pfuma yeiyi IsCancellationRequested uye nzira ThrowIfCancelRequested. Iyo yekupedzisira ichakanda kusarudzika TaskCancelledException kana nzira yeCancellation yakadanwa paCancellationToken muenzaniso ichipepetwa. Uye iyi ndiyo nzira yandinokurudzira kushandisa. Uku ndiko kunatsiridza pane zvakapfuura sarudzo nekuwana kutonga kwakazara pamusoro pekuti inguva ipi iyo basa rekunze rinogona kubviswa.

Iyo yakanyanya hutsinye sarudzo yekumisa tambo ndeyekufonera iyo Win32 API TerminateThread basa. Maitiro eCLR mushure mekudana basa iri rinogona kunge risingafungidzike. PaMSDN zvinotevera zvakanyorwa nezve basa iri: "TerminateThread ibasa rine njodzi rinongofanira kushandiswa mumamiriro ezvinhu akanyanya. β€œ

Kushandura legacy API kuita Task Based uchishandisa FromAsync nzira

Kana iwe uine rombo rakanaka rekushanda purojekiti yakatangwa mushure mekunge Mabasa akaunzwa uye akarega kukonzera kunyarara kutyisa kune vazhinji vanogadzira, saka haufanirwe kutarisana neakawanda ekare maAPI, ese echitatu-bato uye ayo timu yako. akatambudza kare. Sezvineiwo, boka reNET Framework rakatichengeta, kunyange zvazvo zvichida chinangwa chaiva chokuzvichengeta. Iva sezvazvingaite, .NET ine maturusi akati wandei ekushandura zvisingarwadze kodhi yakanyorwa mukare asynchronous programming approaches kune itsva. Imwe yacho ndiyo FromAsync nzira yeTaskFactory. Mumuenzaniso wekodhi pazasi, ndinoputira nzira dzekare dzeasynchronous dzeWebRequest kirasi muTask uchishandisa nzira iyi.

object state = null;
WebRequest wr = WebRequest.CreateHttp("http://github.com");
await Task.Factory.FromAsync(
    wr.BeginGetResponse,
    we.EndGetResponse
);

Uyu ungori muenzaniso uye haufanirwe kuita izvi nemhando dzakavakirwa-mukati, asi chero chirongwa chekare chiri kungozara neBeginDoSomething nzira dzinodzosera IAsyncResult uye EndDoSomething nzira dzinoigamuchira.

Shandura legacy API kuita Task Based uchishandisa TaskCompletionSource kirasi

Chimwe chishandiso chakakosha chekufunga nezvacho ikirasi TaskCompletionSource. Panyaya yemabasa, chinangwa uye musimboti wekushanda, zvinogona kunge zvakatiyeuchidza nezveRegisterWaitForSingleObject nzira ye ThreadPool kirasi, yandakanyora pamusoro. Uchishandisa kirasi iyi, unogona nyore uye zviri nyore kuputira ekare asynchronous APIs muMabasa.

Iwe uchati ini ndakatotaura nezveKubvaAsync nzira yeTaskFactory kirasi yakagadzirirwa izvi zvinangwa. Pano tichafanira kuyeuka nhoroondo yose yekugadzirwa kweasynchronous models mu .net iyo Microsoft yakapa mumakore gumi nemashanu apfuura: pamberi peTask-Based Asynchronous Pattern (TAP), paiva neAsynchronous Programming Pattern (APP), iyo yakanga iri nzira TangaDoSomething returning IAsyncResult uye nzira magumoDoSomething chinochigamuchira uye chenhaka yemakore aya nzira yeKubvaAsync yakangonaka, asi nekufamba kwenguva, yakatsiviwa neChiitiko Chinobva Asynchronous Pattern (UYE AP), iyo yaifungidzira kuti chiitiko chaizosimudzwa kana asynchronous oparesheni yapera.

TaskCompletionSource yakanakira kuputira Mabasa uye legacy APIs akavakwa kutenderedza chiitiko modhi. Izvo zvakakosha zvebasa rayo ndezvizvi: chinhu chekirasi iyi ine pfuma yeruzhinji yerudzi rweTask, iyo nyika inogona kudzorwa kuburikidza neSetResult, SetException, etc. nzira dzeTaskCompletionSource kirasi. Munzvimbo idzo akamirira mushandisi akaiswa kune Task iyi, ichaitwa kana kukundikana pamwe chete zvichienderana nenzira yakashandiswa kuTaskCompletionSource. Kana zvisati zvajeka, ngatitarisei iyi kodhi muenzaniso, apo imwe yekare EAP API yakaputirwa muTask uchishandisa TaskCompletionSource: kana chiitiko ichipisa, Basa rinoendeswa kune Yakapedzwa nyika, uye nzira yakashandisa akamirira opareta. kune Task iyi ichatangazve kuurayiwa kwayo yagamuchira chinhu result.

public static Task<Result> DoAsync(this SomeApiInstance someApiObj) {

    var completionSource = new TaskCompletionSource<Result>();
    someApiObj.Done += 
        result => completionSource.SetResult(result);
    someApiObj.Do();

    result completionSource.Task;
}

TaskCompletionSource Mazano & Tricks

Kupeta ekare APIs hazvisi zvese zvinogona kuitwa uchishandisa TaskCompletionSource. Kushandisa kirasi iyi kunovhura mukana unonakidza wekugadzira akasiyana APIs paMabasa asingatore tambo. Uye rukova, sezvatinorangarira, chinhu chinodhura uye nhamba yavo ishoma (kunyanya nehuwandu hwe RAM). Izvi zvinogumira zvinogona kuwanikwa zviri nyore nekugadzira, semuenzaniso, yakatakurwa yewebhu application ine yakaoma bhizinesi logic. Ngatitarisei mikana yandiri kutaura nezvayo pakuita hunyengeri hwakadai seLong-Polling.

Muchidimbu, chinangwa chehunyengeri ndeichi: unoda kugamuchira ruzivo kubva kuAPI pamusoro pezvimwe zviitiko zviri kuitika kurutivi rwayo, nepo API, nokuda kwechimwe chikonzero, haigoni kutaurira chiitiko chacho, asi inogona kungodzorera nyika. Muenzaniso weiyi yose APIs yakavakirwa pamusoro peHTTP nguva isati yasvika yeWebSocket kana kuti pazvaive zvisingakwanisi kune chimwe chikonzero chekushandisa tekinoroji iyi. Mutengi anogona kubvunza sevha yeHTTP. Sevha yeHTTP haigone kutanga kutaurirana nemutengi. Mhinduro iri nyore ndeyekuvhota sevha uchishandisa timer, asi izvi zvinogadzira imwezve mutoro pane sevha uye kumwe kunonoka paavhareji TimerInterval / 2. Kuti utenderere neizvi, chitsotsi chinonzi Long Polling chakagadzirwa, chinosanganisira kunonoka mhinduro kubva. server kusvika Timeout yapera kana kuti chiitiko chichaitika. Kana chiitiko chacho chakaitika, zvino chinogadziriswa, kana zvisingaiti, ipapo chikumbiro chinotumirwa zvakare.

while(!eventOccures && !timeoutExceeded)  {

  CheckTimout();
  CheckEvent();
  Thread.Sleep(1);
}

Asi mhinduro yakadaro icharatidza kuva inotyisa nokukurumidza apo nhamba yevatengi vakamirira chiitiko ichiwedzera, nokuti ... Mumwe nemumwe mutengi akadaro anotora tambo yese yakamirira chiitiko. Ehe, uye isu tinowana yekuwedzera 1ms kunonoka kana chiitiko chatanga, kazhinji izvi hazvina kukosha, asi nei kuita kuti software iwedzere kupfuura zvazvingaite? Kana tikabvisa Thread.Kurara (1), ipapo pasina isu tichatakura imwe processor core 100% isina basa, ichitenderera mumhepo isingabatsiri. Uchishandisa TaskCompletionSource unogona kuita zvakare kodhi iyi nyore uye kugadzirisa matambudziko ese akaonekwa pamusoro:

class LongPollingApi {

    private Dictionary<int, TaskCompletionSource<Msg>> tasks;

    public async Task<Msg> AcceptMessageAsync(int userId, int duration) {

        var cs = new TaskCompletionSource<Msg>();
        tasks[userId] = cs;
        await Task.WhenAny(Task.Delay(duration), cs.Task);
        return cs.Task.IsCompleted ? cs.Task.Result : null;
    }

    public void SendMessage(int userId, Msg m) {

        if (tasks.TryGetValue(userId, out var completionSource))
            completionSource.SetResult(m);
    }
}

Iyi kodhi haina kugadzirwa-yakagadzirira, asi ingori demo. Kuti uishandise mumamiriro ezvinhu chaiwo, unodawo, zvishoma, kubata mamiriro ezvinhu apo meseji inosvika panguva iyo pasina munhu ari kuitarisira: munyaya iyi, nzira yeAsseptMessageAsync inofanira kudzorera Basa rakatopera. Kana iyi iriyo nyaya yakajairika, saka unogona kufunga nezve kushandisa ValueTask.

Kana isu tagamuchira chikumbiro chemeseji, tinogadzira uye tinoisa TaskCompletionSource muduramazwi, uye tomirira izvo zvinotanga kuitika: nguva yakatarwa inopera kana meseji inogamuchirwa.

ValueTask: sei uye sei

The async / kumirira vashandi, kufanana negoho rekudzorera opareta, gadzira muchina wehurumende kubva kune nzira, uye uku ndiko kusikwa kwechinhu chitsva, chinenge chisingawanzo kukosha, asi muzviitiko zvisingawanzoitiki zvinogona kugadzira dambudziko. Nyaya iyi inogona kunge iri nzira inodaidzwa chaizvo kazhinji, tiri kutaura nezve makumi nemazana ezviuru zvekufona pasekondi. Kana nzira yakadai yakanyorwa nenzira yekuti kazhinji inodzorera chigumisiro ichidarika nzira dzose dzakamirira, ipapo NET inopa chigadziro chekugadzirisa izvi - ValueTask structure. Kuti zvijeke, ngatitarisei muenzaniso wekushandiswa kwayo: pane cache yatinoenda kakawanda. Iine humwe hutsika uye isu tinongozvidzosera; kana zvisiri, tobva taenda kune imwe inononoka IO kuti tiiwane. Ini ndoda kuita iyo yekupedzisira asynchronously, zvinoreva kuti iyo nzira yese inoshanduka kuita asynchronous. Nokudaro, nzira iri pachena yekunyora nzira ndeyotevera:

public async Task<string> GetById(int id) {

    if (cache.TryGetValue(id, out string val))
        return val;
    return await RequestById(id);
}

Nekuda kwechishuwo chekugadzirisa zvishoma, uye kutya kushoma kweizvo Roslyn achagadzira kana achigadzira iyi kodhi, unogona kunyora uyu muenzaniso sezvinotevera:

public Task<string> GetById(int id) {

    if (cache.TryGetValue(id, out string val))
        return Task.FromResult(val);
    return RequestById(id);
}

Hongu, mhinduro yakakwana mune iyi kesi ingave yekukwiridzira nzira inopisa, kureva, kuwana kukosha kubva muduramazwi pasina kugovewa kusingakoshi uye kurodha paGC, nepo mune izvo zvisingawanzo zviitiko apo isu tichiri kuda kuenda kuIO kune data. , zvese zvicharamba zviri kuwedzera / kubvisa nzira yekare:

public ValueTask<string> GetById(int id) {

    if (cache.TryGetValue(id, out string val))
        return new ValueTask<string>(val);
    return new ValueTask<string>(RequestById(id));
}

Ngatinyatsoongororai chikamu chekodhi iyi: kana pane kukosha mu cache, tinogadzira chimiro, kana zvisina kudaro basa rechokwadi richaputirwa mune rine musoro. Kodhi yekufona haina basa kuti ndeipi nzira yakaitwa iyi kodhi mu: ValueTask, kubva paC # syntax point yekuona, ichaita zvakafanana neBasa renguva dzose mune iyi kesi.

TaskSchedulers: kubata basa rekutanga maitiro

Iyo inotevera API yandinoda kufunga nezve kirasi TaskScheduler uye zvinobva pazviri. Ini ndakatotaura pamusoro apa kuti TPL inokwanisa kubata nzira dzekugovera Mabasa mukati meshinda. Mazano akadaro anotsanangurwa muvazukuru veTaskScheduler kirasi. Anenge chero zano raungade rinogona kuwanikwa muraibhurari. ParallelExtensionsExtras, yakagadziridzwa neMicrosoft, asi kwete chikamu che.NET, asi inopiwa sepakeji yeNuget. Ngatitarisei muchidimbu zvimwe zvacho:

  • CurrentThreadTaskScheduler - inoita Mabasa pane yazvino shinda
  • LimitedConcurrencyLevelTaskScheduler - inodzika nhamba yeMabasa akaitwa panguva imwe chete neparameter N, inogamuchirwa muvaki
  • OrderedTaskScheduler - inotsanangurwa se LimitedConcurrencyLevelTaskScheduler(1), saka mabasa achaitwa achitevedzana.
  • WorkStealingTaskScheduler - midziyo basa-kuba nzira yekugovera basa. Chaizvoizvo iyo yakaparadzana ThreadPool. Inogadzirisa dambudziko iro mu.NET ThreadPool is a static class, imwe yezvikumbiro zvose, zvinoreva kuti kuwandisa kwayo kana kushandiswa kusina kunaka mune chimwe chikamu chepurogiramu kunogona kutungamirira kune migumisiro mune imwe. Uyezve, zvakaoma zvikuru kunzwisisa chikonzero chezvikanganiso zvakadaro. Izvozvo. Panogona kuve nekudikanwa kwekushandisa yakaparadzana WorkStealingTaskSchedulers muzvikamu zvechirongwa uko kushandiswa kweThreadPool kungave kwehasha uye kusingatarisike.
  • QueuedTaskScheduler - inokutendera kuti uite mabasa zvinoenderana nemirairo yemutsetse
  • ThreadPerTaskScheduler - inogadzira tambo yakaparadzana kune yega yega Basa rinoitwa pairi. Inogona kubatsira kune mabasa anotora nguva yakareba isingafungidzike kuti apedze.

Pane yakanaka yakatsanangurwa chinyorwa nezve TaskSchedulers pane iyo microsoft blog.

Kuti zvive nyore kugadzirisa zvese zvine chekuita neMabasa, Visual Studio ine Task hwindo. Muhwindo iri unogona kuona mamiriro azvino ebasa uye svetukira kumutsetse wekuita wekodhi ikozvino.

.NET: Zvishandiso zvekushanda nemultithreading uye asynchrony. Chikamu 1

PLinq uye Parallel kirasi

Kuwedzera kune Mabasa uye zvese zvakataurwa pamusoro pavo, kune mamwe maviri anonakidza maturusi mu.NET: PLinq (Linq2Parallel) uye Parallel kirasi. Yekutanga inovimbisa kuita kwakafanana kwese kweLinq mashandiro pane akawanda shinda. Huwandu hwetambo hunogona kugadzirwa uchishandisa iyo WithDegreeOfParallelism yekuwedzera nzira. Nehurombo, kazhinji PLinq mune yayo yekusarudzika modhi haina ruzivo rwakakwana nezve emukati meiyo data sosi kuti ipe yakakosha kukurumidza kuwana, kune rumwe rutivi, mutengo wekuyedza wakaderera kwazvo: iwe unongoda kufonera iyo AsParallel nzira pamberi. iyo ketani yeLinq nzira uye mhanyisa bvunzo dzekuita. Zvakare, zvinogoneka kupfuudza rumwe ruzivo kuPLinq nezve chimiro che data yako sosi uchishandisa iyo Partitions michina. Unogona kuverenga zvakawanda pano ΠΈ pano.

Iyo Parallel static kirasi inopa nzira dzekudzokorodza kuburikidza neForeach muunganidzwa wakafanana, kuita For loop, uye kuuraya akawanda nhume mune yakafanana Invoke. Kuitwa kweshinda yazvino kuchamiswa kusvika masvomhu apera. Huwandu hwetambo hunogona kugadzirwa nekupfuura ParallelOptions senharo yekupedzisira. Iwe unogona zvakare kutsanangura TaskScheduler uye CancellationToken uchishandisa sarudzo.

zvakawanikwa

Pandakatanga kunyora chinyorwa ichi zvichienderana nemidziyo yemushumo wangu uye ruzivo rwandakaunganidza panguva yebasa rangu mushure mayo, ndakanga ndisingatarisiri kuti paizova nezvakawanda kwazvo. Zvino, kana mupepeti wemavara mandiri kunyora chinyorwa ichi achindizvidza achindiudza kuti peji 15 yaenda, ndichapfupisa mhinduro dzenguva pfupi. Mamwe manomano, maAPI, maturusi ekuona uye misungo ichavharwa muchinyorwa chinotevera.

Mhedziso:

  • Iwe unofanirwa kuziva maturusi ekushanda neshinda, asynchrony uye parallelism kuitira kushandisa zviwanikwa zvemazuva ano maPC.
  • .NET ine zvishandiso zvakawanda zvakasiyana zvezvinangwa izvi
  • Haasi ese akaonekwa kamwechete, saka iwe unogona kazhinji kuwana nhaka, zvisinei, kune nzira dzekushandura ekare maAPI pasina kushanda nesimba.
  • Kushanda neshinda mu.NET inomiririrwa nemakirasi eThread neThreadPool
  • Iyo Thread.Abort, Thread.Interrupt, uye Win32 API TerminateThread nzira dzine njodzi uye hadzikurudzirwe kushandiswa. Pane kudaro, zviri nani kushandisa CancellationToken mechanism
  • Kuyerera chinhu chakakosha sosi uye kupa kwayo kunogumira. Mamiriro ezvinhu apo tambo dzakabatikana dzakamirira zviitiko dzinofanira kudziviswa. Kune izvi zviri nyore kushandisa TaskCompletionSource kirasi
  • Izvo zvine simba zvakanyanya uye zvepamberi .NET zvishandiso zvekushanda neparallelism uye asynchrony ndiwo Mabasa.
  • Iyo c# async/kumirira vashandisi vanoita iyo pfungwa yekusavharira kumirira
  • Iwe unogona kudzora kugoverwa kweMatask pane tambo uchishandisa TaskScheduler-yakatorwa makirasi
  • Iyo ValueTask chimiro inogona kubatsira mukugadzirisa inopisa-nzira uye ndangariro-traffic
  • Visual Studio's Tasks uye Threads windows inopa ruzivo rwakawanda runobatsira kugadzirisa ma-multi-threaded kana asynchronous code.
  • PLinq chishandiso chinotonhorera, asi chinogona kunge chisina ruzivo rwakakwana nezve yako data sosi, asi izvi zvinogona kugadziriswa uchishandisa nzira yekugovera.
  • Zvichaenderera mberi…

Source: www.habr.com

Voeg