NET: Zida zogwirira ntchito ndi multithreading ndi asynchrony. Gawo 1

Ndikusindikiza nkhani yoyambirira ya Habr, kumasulira kwake kumayikidwa mukampani positi blog.

Kufunika kochita chinachake mwachisawawa, popanda kuyembekezera zotsatira pano ndi tsopano, kapena kugawa ntchito yaikulu pakati pa mayunitsi angapo omwe akuchita, kunalipo kale makompyuta asanabwere. Ndi kudza kwawo, chosowa ichi chinakhala chogwirika kwambiri. Tsopano, mu 2019, ndikulemba nkhaniyi pa laputopu yokhala ndi purosesa ya 8-core Intel Core, pomwe njira zopitilira zana zikuyenda mofanana, komanso ulusi wochulukirapo. Pafupi, pali foni yonyansa pang'ono, yogulidwa zaka zingapo zapitazo, ili ndi purosesa ya 8-core. Zida zam'mutu ndizodzaza ndi zolemba ndi makanema pomwe olemba awo amasilira mafoni apamwamba a chaka chino omwe ali ndi mapurosesa a 16-core. MS Azure imapereka makina enieni okhala ndi 20 core processor ndi 128 TB RAM osakwana $2/ola. Tsoka ilo, ndizosatheka kutulutsa kuchuluka kwake ndikugwiritsa ntchito mphamvuyi popanda kutha kuyendetsa kulumikizana kwa ulusi.

Mawu omaliza

Njira - OS chinthu, malo adilesi akutali, ali ndi ulusi.
Ulusi - chinthu cha OS, gawo laling'ono kwambiri la kuphedwa, gawo la ndondomeko, ulusi umagawana kukumbukira ndi zinthu zina pakati pawo mkati mwa ndondomeko.
Multitasking - Katundu wa OS, kuthekera koyendetsa njira zingapo nthawi imodzi
Multi-core - katundu wa purosesa, kuthekera kogwiritsa ntchito ma cores angapo pokonza deta
Multiprocessing - katundu wa kompyuta, luso lotha kugwira ntchito limodzi ndi mapurosesa angapo mwakuthupi
Multithreading - katundu wa ndondomeko, kuthekera kugawa deta processing pakati pa ulusi angapo.
Kufanana - kuchita zinthu zingapo nthawi imodzi panthawi imodzi
Asynchrony - kugwira ntchito popanda kuyembekezera kukwaniritsidwa kwa ntchitoyi; zotsatira za kuphedwa zikhoza kukonzedwa pambuyo pake.

Mafanizo

Si matanthauzo onse omwe ali abwino ndipo ena amafunikira kufotokozera kwina, kotero ndiwonjezera fanizo lokhudza kuphika chakudya cham'mawa ku mawu odziwika bwino. Kuphika chakudya cham'mawa mu fanizo ili ndi njira.

Ndikukonzekera kadzutsa m'mawa ine (CPUNditafika ku kitchen (kompyuta). Ndili ndi manja 2 (mitima). Pali zida zingapo kukhitchini (IO): uvuni, ketulo, toaster, firiji. Ndimayatsa gasi, ndikuyika poto ndikutsanulira mafuta osadikirira kuti atenthe.asynchronously, Non-blocking-IO-Wait), ndimatulutsa mazira mufiriji ndikuphwanya mbale, kenako ndikumenya ndi dzanja limodzi (Ulusi #1), ndi chachiwiri (Ulusi #2) kugwira mbale (Shared Resource). Tsopano ndikufuna kuyatsa ketulo, koma ndilibe manja okwanira (Ulusi Njala) Panthawiyi, poto yokazinga imatentha (Kukonza zotsatira) momwe ndimathira zomwe ndakwapula. Ndifikira ketulo ndikuyatsa ndikuwona madzi akuwira mmenemo (Kuletsa-IO-Dikirani), ngakhale panthawiyi akanatha kutsuka mbale yomwe amakwapula omelet.

Ndinaphika omelet pogwiritsa ntchito manja awiri okha, ndipo ndilibe zambiri, koma nthawi yomweyo, panthawi yokwapula omelet, ma omelette atatu anachitika nthawi imodzi: kukwapula omelet, kugwira mbale, kutentha poto yokazinga. CPU ndiye gawo lachangu kwambiri pakompyuta, IO ndi yomwe nthawi zambiri imachedwetsa chilichonse, nthawi zambiri njira yabwino ndikutenga CPU ndi china chake ndikulandila data kuchokera ku IO.

Kupitiliza fanizoli:

  • Ngati ndikukonzekera omelet, ndingayesenso kusintha zovala, izi zingakhale chitsanzo cha multitasking. Chofunika kwambiri: makompyuta ndi abwino kwambiri pa izi kuposa anthu.
  • Khitchini yokhala ndi ophika angapo, mwachitsanzo mu malo odyera - makompyuta ambiri.
  • Malo ambiri odyera m'bwalo lazakudya m'malo ogulitsira - data center

.NET Zida

.NET ndi yabwino kugwira ntchito ndi ulusi, monga ndi zinthu zina zambiri. Ndi mtundu uliwonse watsopano, imabweretsa zida zatsopano zogwirira ntchito nawo, zigawo zatsopano zotsalira pa ulusi wa OS. Pogwira ntchito yomanga abstractions, okonza chimango amagwiritsa ntchito njira yomwe imasiya mwayi, pogwiritsira ntchito kuchotsedwa kwapamwamba, kutsika pansi pamlingo umodzi kapena zingapo pansipa. Nthawi zambiri izi sizofunika, kwenikweni zimatsegula chitseko chowombera phazi ndi mfuti, koma nthawi zina, nthawi zina, ikhoza kukhala njira yokhayo yothetsera vuto lomwe silinathetsedwe pakalipano. .

Ndi zida, ndikutanthauza ma interfaces ogwiritsira ntchito mapulogalamu (APIs) operekedwa ndi chimango ndi phukusi lachitatu, komanso mayankho apulogalamu onse omwe amathandizira kusaka kwamavuto aliwonse okhudzana ndi ma code amitundu yambiri.

Kuyambira ulusi

The Thread class ndiye kalasi yofunikira kwambiri mu .NET pogwira ntchito ndi ulusi. Wopanga amavomereza mmodzi mwa nthumwi ziwiri:

  • ThreadStart - Palibe magawo
  • ParametrizedThreadStart - yokhala ndi gawo limodzi la mtundu wa chinthu.

Nthumwi idzaphedwa mu ulusi wopangidwa kumene pambuyo poyitana njira Yoyambira Ngati nthumwi ya mtundu wa ParametrizedThreadStart inaperekedwa kwa womanga, ndiye kuti chinthu chiyenera kuperekedwa ku Njira Yoyambira. Dongosololi limafunikira kusamutsa zambiri zamderali kumtsinje. Ndizofunikira kudziwa kuti kupanga ulusi ndi ntchito yokwera mtengo, ndipo ulusiwo ndi chinthu cholemetsa, chifukwa amagawa 1MB ya kukumbukira pamtengo ndipo amafuna kuyanjana ndi OS API.

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

Kalasi ya ThreadPool imayimira lingaliro la dziwe. Mu .NET, dziwe la ulusi ndi gawo la uinjiniya, ndipo opanga ku Microsoft achita khama kwambiri kuti awonetsetse kuti imagwira ntchito bwino pazochitika zosiyanasiyana.

Lingaliro lazonse:

Kuyambira pomwe pulogalamuyo imayamba, imapanga ulusi wambiri kumbuyo ndikupatseni mwayi woti mugwiritse ntchito. Ngati ulusi ukugwiritsidwa ntchito pafupipafupi komanso mochuluka, dziwe limakula kuti likwaniritse zosowa za woyimbirayo. Pamene palibe ulusi waulere mu dziwe pa nthawi yoyenera, imadikirira kuti ulusi ubwerere, kapena upange watsopano. Izi ndichifukwa choti ulusiwu ndi wabwino kwambiri pakanthawi kochepa komanso suyenera kugwiritsidwa ntchito ngati ntchito panthawi yonse ya pulogalamuyo.

Kuti mugwiritse ntchito ulusi wochokera padziwe, pali njira ya QueueUserWorkItem yomwe imavomereza nthumwi ya mtundu wa WaitCallback, yomwe ili ndi siginecha yofanana ndi ParametrizedThreadStart, ndipo chizindikiro choperekedwa kwa icho chimagwira ntchito yomweyo.

ThreadPool.QueueUserWorkItem(...);

Njira yodziwika bwino ya ulusi ya RegisterWaitForSingleObject imagwiritsidwa ntchito kukonza ma IO osatsekereza. Nthumwi yoperekedwa ku njirayi idzatchedwa WaitHandle itadutsa njira "Yotulutsidwa".

ThreadPool.RegisterWaitForSingleObject(...)

.NET ili ndi timer ya ulusi ndipo imasiyana ndi nthawi ya WinForms/WPF chifukwa chothandizira chake chidzatchedwa ulusi wotengedwa padziwe.

System.Threading.Timer

Palinso njira yachilendo yotumizira nthumwi kuti ikaphedwe ku ulusi wochokera padziwe - njira ya BeginInvoke.

DelegateInstance.BeginInvoke

Ndikufuna kukamba mwachidule za ntchito yomwe njira zambiri zomwe zili pamwambazi zitha kutchedwa - CreateThread kuchokera ku Kernel32.dll Win32 API. Pali njira, chifukwa cha makina a njira zakunja, kutchula ntchitoyi. Ndawonapo kuyitanidwa kotere kamodzi kokha m'chitsanzo choyipa cha code cholowa, ndipo zolimbikitsa za wolemba yemwe adachita izi zikadali chinsinsi kwa ine.

Kernel32.dll CreateThread

Kuwona ndi Kuthetsa Ulusi

Ulusi wopangidwa ndi inu, zigawo zonse za chipani chachitatu, ndi dziwe la .NET likhoza kuwonedwa pawindo la Threads la Visual Studio. Zenerali limangowonetsa zambiri za ulusi pomwe pulogalamuyo ili pansi pa debug komanso mu Break mode. Apa mutha kuwona mosavuta mayina aulukidwe ndi zofunika pa ulusi uliwonse, ndikusintha kukonza ku ulusi wina. Pogwiritsa ntchito katundu Wofunika Kwambiri wa Thread class, mutha kuyika patsogolo ulusi, womwe OC ndi CLR adzawona ngati malingaliro pogawa nthawi ya purosesa pakati pa ulusi.

NET: Zida zogwirira ntchito ndi multithreading ndi asynchrony. Gawo 1

Task Parallel Library

Task Parallel Library (TPL) idayambitsidwa mu .NET 4.0. Tsopano ndiye muyezo komanso chida chachikulu chogwirira ntchito ndi asynchrony. Khodi iliyonse yomwe imagwiritsa ntchito njira yakale imatengedwa ngati cholowa. Chigawo choyambirira cha TPL ndi Task class kuchokera ku System.Threading.Tasks namespace. Ntchito ndi chidule cha ulusi. Ndi mtundu watsopano wa chilankhulo cha C #, tili ndi njira yabwino kwambiri yogwirira ntchito ndi Ma Tasks - async/await operators. Mfundozi zinapangitsa kuti zikhale zotheka kulemba kachidindo ka asynchronous ngati kuti ndi yosavuta komanso yogwirizana, izi zinapangitsa kuti ngakhale anthu omwe samvetsa bwino za mkati mwa ulusi alembe mapulogalamu omwe amawagwiritsa ntchito, ntchito zomwe sizimaundana pochita ntchito zazitali. Kugwiritsa ntchito async/kudikira ndi mutu wankhani imodzi kapena zingapo, koma ndiyesera kupeza mfundo zake m'masentensi angapo:

  • async ndikusintha njira yobwezera Ntchito kapena zopanda pake
  • ndipo kuyembekezera ndi wogwiritsa ntchito wosatsekereza Task yodikira.

Apanso: woyembekezera, nthawi zambiri (pali zopatula), adzatulutsa ulusi wamakono wakupha, ndipo Ntchito ikamaliza kuphedwa kwake, ndi ulusi (kwenikweni, zingakhale zolondola kunena nkhaniyo. , koma zambiri pambuyo pake) ipitiliza kugwiritsa ntchito njirayo. Mkati .NET, makinawa akugwiritsidwa ntchito mofanana ndi kubwerera kwa zokolola, pamene njira yolembedwa imasandulika kukhala gulu lonse, lomwe ndi makina a boma ndipo akhoza kuphedwa mu zidutswa zosiyana malingana ndi mayiko awa. Aliyense amene ali ndi chidwi atha kulemba kachidindo kalikonse kosavuta pogwiritsa ntchito asynс/await, kusonkhanitsa ndikuwona msonkhanowo pogwiritsa ntchito JetBrains dotPeek yokhala ndi Compiler Generated Code yathandizidwa.

Tiyeni tiwone zosankha zoyambira ndikugwiritsa ntchito Task. Muchitsanzo cha code pansipa, timapanga ntchito yatsopano yomwe sichita chilichonse chothandiza (Ulusi.Tulo(10000)), koma m'moyo weniweni izi ziyenera kukhala ntchito yovuta kwambiri ya CPU.

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
}

Ntchito imapangidwa ndi zosankha zingapo:

  • LongRunning ndi lingaliro lakuti ntchitoyi siidzatha mwamsanga, zomwe zikutanthauza kuti zingakhale zoyenera kuganizira kuti musatenge ulusi kuchokera padziwe, koma kupanga chosiyana cha Ntchitoyi kuti musavulaze ena.
  • AttachedToParent - Ntchito zitha kukonzedwa motsatira utsogoleri. Ngati njirayi idagwiritsidwa ntchito, ndiye kuti Ntchitoyo ikhoza kukhala m'malo pomwe idamaliza ndipo ikuyembekezera kuphedwa kwa ana ake.
  • PreferFairness - zikutanthauza kuti zingakhale bwino kuchita Ntchito zomwe zidatumizidwa kale zisanatumizidwe pambuyo pake. Koma izi ndi malingaliro chabe ndipo zotsatira zake sizotsimikizika.

Gawo lachiwiri lomwe ladutsa njirayo ndi CancellationToken. Kuti muthane bwino ndi kuletsa ntchitoyo ikayamba, code yomwe ikuchitidwa iyenera kudzazidwa ndi macheke a CancellationToken state. Ngati palibe macheke, ndiye kuti Njira Yoletsa yoyitanidwa pa chinthu cha CancellationTokenSource idzatha kuyimitsa ntchitoyo isanayambe.

Chotsatira chomaliza ndi chinthu chokonzekera cha mtundu wa TaskScheduler. Gululi ndi mbadwa zake adapangidwa kuti aziwongolera njira zogawira Ma Tasks mu ulusi uliwonse; mwachisawawa, Ntchitoyi idzachitidwa pa ulusi wosasintha kuchokera padziwe.

Woyang'anira akudikirira akugwiritsidwa ntchito ku Ntchito yopangidwa, zomwe zikutanthauza kuti code yolembedwa pambuyo pake, ngati ilipo, idzachitidwa mofanana (nthawi zambiri izi zikutanthauza pa ulusi womwewo) monga code isanayambe kuyembekezera.

Njirayi imalembedwa ngati async void, zomwe zikutanthauza kuti ikhoza kugwiritsa ntchito woyembekezera, koma nambala yoyimbira siingathe kudikirira kuphedwa. Ngati izi ndizofunikira, ndiye kuti njirayo iyenera kubwerera Ntchito. Njira zodziwika kuti async void ndizofala kwambiri: monga lamulo, awa ndi othandizira zochitika kapena njira zina zomwe zimagwira ntchito pamoto ndikuyiwala mfundo. Ngati simukuyenera kupereka mwayi wodikirira mpaka kumapeto kwa kuphedwa, komanso kubwezera zotsatira, ndiye kuti muyenera kugwiritsa ntchito Task.

Pa Ntchito yomwe njira ya StartNew yabwerera, komanso ina iliyonse, mutha kuyimbira njira ya ConfigureAwait ndi parameter yonyenga, ndiye kuti kuphedwa pambuyo kuyembekezera sikudzapitilirabe pazomwe zalandidwa, koma mosasamala. Izi ziyenera kuchitika nthawi zonse pamene zochitika zakupha sizili zofunikira pa code pambuyo poyembekezera. Izi ndi malingaliro ochokera kwa MS polemba khodi yomwe idzaperekedwa mulaibulale.

Tiyeni tikambirane pang'ono za momwe mungadikire kumaliza ntchito. Pansipa pali chitsanzo cha kachidindo, ndi ndemanga za nthawi yomwe kuyembekezera kuchitidwa bwino komanso ngati kuchitidwa molakwika.

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
}

Muchitsanzo choyamba, timadikirira kuti Ntchitoyo ithe popanda kutsekereza ulusi woyimbira; tidzabwereranso kukakonza zotsatirazo zitakhala kale; mpaka pamenepo, ulusi woyimbira umasiyidwa ku zida zake.

Mu njira yachiwiri, timaletsa ulusi woyitana mpaka zotsatira za njirayo ziwerengedwe. Izi ndizoipa osati chifukwa takhala ndi ulusi, chida chofunika kwambiri cha pulogalamuyo, ndi kusasamala kosavuta, komanso chifukwa ngati ndondomeko ya njira yomwe timayitana ili ndi kuyembekezera, ndi kugwirizanitsa nkhani kumafuna kubwerera ku ulusi woyitana pambuyo pake. dikirani, ndiye tidzakhala ndi nthawi yomaliza : Ulusi woyitana ukudikira pamene zotsatira za njira ya asynchronous ikuwerengedwa, njira ya asynchronous imayesa pachabe kupitiriza kuchitidwa mu ulusi woyitana.

Choyipa china cha njirayi ndizovuta kuthana ndi zolakwika. Chowonadi ndi chakuti zolakwika mu code asynchronous mukamagwiritsa ntchito async / await ndizosavuta kuthana nazo - amachita chimodzimodzi ngati kuti codeyo inali yolumikizana. Ngakhale titagwiritsa ntchito synchronous wait exorcism ku Task, kupatula koyambirira kumasanduka AggregateException, i.e. Kuti muthane ndi izi, muyenera kuyang'ana mtundu wa InnerException ndikulemba ngati unyolo mkati mwa chipika chimodzi kapena mugwiritse ntchito nsomba pomanga, m'malo mwa midadada yamagulu omwe amadziwika kwambiri padziko la C #.

Chitsanzo chachitatu komanso chomaliza chalembedwanso choyipa pazifukwa zomwezo ndipo chili ndi mavuto ofanana.

Njira za WhenAny ndi WhenAll ndizosavuta kudikirira gulu la Ntchito; amakulunga gulu la Ntchito kukhala imodzi, yomwe imatha kuwotcha ngati Ntchito ya gulu iyambika, kapena onse akamaliza kuphedwa.

Kuyimitsa ulusi

Pazifukwa zosiyanasiyana, pangakhale koyenera kuyimitsa kuyenderera pambuyo poyambira. Pali njira zingapo zochitira izi. Gulu la Thread lili ndi njira ziwiri zotchulidwa moyenera: Kutaya mimba и Kusokoneza. Yoyamba ndiyosavomerezeka kuti igwiritsidwe ntchito, chifukwa atayitcha nthawi iliyonse mwachisawawa, pakukonzekera malangizo aliwonse, chosiyana chidzatayidwa ThreadAbortedException. Simuyembekezera kuti izi zitha kuponyedwa mukamawonjezera kusinthika kulikonse, sichoncho? Ndipo mukamagwiritsa ntchito njirayi, izi ndizochitika zenizeni. Ngati mukufuna kuletsa CLR kuti isapange zosiyana ndi gawo linalake la code, mutha kuyikulunga pama foni. Thread.BeginCriticalRegion, Thread.EndCriticalRegion. Khodi iliyonse yolembedwa mu block yomaliza imakutidwa ndi mafoni otere. Pachifukwa ichi, mu kuya kwa chimango code mungapeze midadada ndi kuyesa opanda kanthu, koma opanda kanthu potsiriza. Microsoft imaletsa njirayi kwambiri kotero kuti sanayiphatikize mu .net core.

Njira ya Interrupt imagwira ntchito bwino kwambiri. Ikhoza kusokoneza ulusi pokhapokha ThreadInterruptedException pokhapokha panthawi yomwe ulusi uli wodikirira. Imalowa m'derali ndikudikirira WaitHandle, loko, kapena kuitana Thread.Sleep.

Zosankha zonse ziwiri zomwe zafotokozedwa pamwambapa ndi zoyipa chifukwa chosayembekezereka. Yankho lake ndi kugwiritsa ntchito dongosolo CancellationToken ndi class CancellationTokenSource. Mfundo ndi iyi: chitsanzo cha kalasi ya CancellationTokenSource idapangidwa ndipo ndi yekhayo amene ali nayo yemwe angayimitse ntchitoyi poyimbira njirayo. Kuletsa. Ndi CancellationToken yokha yomwe imaperekedwa ku opareshoni yokha. Eni ake a CancellationToken sangathe kuletsa okha ntchitoyo, koma angoyang'ana ngati ntchitoyo yathetsedwa. Pali katundu wa Boolean wa izi ICancellationRequested ndi njira ThrowIfCancelRequested. Otsatira adzaponya zosiyana TaskCancelledException ngati njira ya Cancellation idayitanidwa pa CancellationToken chitsanzo kukhala parroted. Ndipo iyi ndi njira yomwe ndimalimbikitsa kugwiritsa ntchito. Uku ndikuwongolera pazosankha zam'mbuyomu poyang'anira nthawi yomwe ntchito yosiyana ingathetsedwe.

Njira yankhanza kwambiri yoyimitsa ulusi ndikuyimbira Win32 API TerminateThread ntchito. Makhalidwe a CLR atayitana ntchitoyi akhoza kukhala osadziŵika. Pa MSDN zotsatirazi zalembedwa za ntchitoyi: "TerminateThread ndi ntchito yowopsa yomwe iyenera kugwiritsidwa ntchito pazovuta kwambiri. “

Kutembenuza cholowa cha API kukhala Task Based pogwiritsa ntchito njira ya FromAsync

Ngati muli ndi mwayi wogwira ntchito yomwe idayambika pambuyo poti Ntchito idayambitsidwa ndikusiya kuchititsa mantha kwa otukula ambiri, ndiye kuti simudzasowa kuthana ndi ma API akale ambiri, onse a chipani chachitatu ndi gulu lanu. adazunza m'mbuyomu. Mwamwayi, gulu la .NET Framework linatisamalira, ngakhale kuti mwina cholinga chinali kudzisamalira tokha. Zikhale choncho, .NET ili ndi zida zingapo zosinthira mosavutikira zolembedwa m'mapulogalamu akale a asynchronous kupita ku yatsopano. Chimodzi mwa izo ndi FromAsync njira ya TaskFactory. Muchitsanzo cha code pansipa, ndikukulunga njira zakale za async kalasi ya WebRequest mu Ntchito pogwiritsa ntchito njirayi.

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

Ichi ndi chitsanzo chabe ndipo simungathe kuchita izi ndi mitundu yomangidwa, koma pulojekiti iliyonse yakale imangodzaza ndi njira za BeginDoSomething zomwe zimabwezera IAsyncResult ndi EndDoSomething njira zomwe zimalandira.

Sinthani API ya cholowa kukhala Task Based pogwiritsa ntchito TaskCompletionSource kalasi

Chida china chofunikira kuganizira ndi kalasi TaskCompletionSource. Pankhani ya ntchito, cholinga ndi mfundo zogwirira ntchito, zitha kukhala zokumbutsa njira ya RegisterWaitForSingleObject ya kalasi ya ThreadPool, yomwe ndidalemba pamwambapa. Pogwiritsa ntchito kalasi iyi, mutha kukulunga mosavuta komanso mosavuta ma API akale a asynchronous mu Tasks.

Mudzanena kuti ndalankhula kale za njira ya FromAsync ya kalasi ya TaskFactory yomwe idapangidwira izi. Apa tiyenera kukumbukira mbiri yonse ya chitukuko cha zitsanzo asynchronous mu .net kuti Microsoft anapereka pa zaka 15 zapitazi: pamaso pa Task-Based Asynchronous Pattern (TAP), panali Asynchronous Programming Pattern (APP), yomwe. zinali za njira YambaDoSomething kubwerera IAsyncResult ndi njira TSIRIZADoSomething chomwe chimavomereza komanso cholowa chazaka izi njira ya FromAsync ndi yangwiro, koma patapita nthawi, idasinthidwa ndi Chochitika Chotsatira Asynchronous Pattern (EAP), yomwe inkaganiza kuti chochitika chidzakwezedwa pamene ntchito ya asynchronous itatha.

TaskCompletionSource ndiyabwino kukulunga Ma Tasks ndi ma API a cholowa omwe amamangidwa mozungulira mtundu wa chochitikacho. Chofunikira cha ntchito yake ndi motere: chinthu cha kalasiyi chili ndi katundu wapagulu wa mtundu wa Task, dziko lomwe lingathe kuwongoleredwa kudzera mu SetResult, SetException, etc. njira za kalasi ya TaskCompletionSource. M'malo omwe oyembekezera adagwiritsidwa ntchito ku Task iyi, idzachitidwa kapena kulephera kusiyapo kutengera njira yomwe ikugwiritsidwa ntchito ku TaskCompletionSource. Ngati sizikumveka bwino, tiyeni tiwone chitsanzo ichi, pomwe EAP API yakale idakulungidwa mu Ntchito pogwiritsa ntchito TaskCompletionSource: chochitikacho chikayaka, Ntchitoyo idzasamutsidwa ku State Yotsirizidwa, ndi njira yomwe adagwiritsa ntchito woyembekezera. ku Ntchito iyi iyambiranso kuphedwa kwake atalandira chinthucho chifukwa.

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 Malangizo & Zidule

Kukulunga ma API akale sizomwe zingatheke pogwiritsa ntchito TaskCompletionSource. Kugwiritsa ntchito kalasiyi kumatsegula mwayi wosangalatsa wopanga ma API osiyanasiyana pa Ntchito zomwe sizikhala ndi ulusi. Ndipo mtsinjewo, monga tikukumbukira, ndi gwero lamtengo wapatali ndipo chiwerengero chawo ndi chochepa (makamaka ndi kuchuluka kwa RAM). Izi zitha kutheka mosavuta popanga, mwachitsanzo, pulogalamu yodzaza ndi intaneti yokhala ndi malingaliro ovuta abizinesi. Tiyeni tilingalire mwayi womwe ndikunena pokhazikitsa chinyengo monga Polling Long.

Mwachidule, chiyambi cha chinyengo ndi ichi: muyenera kulandira chidziwitso kuchokera ku API za zochitika zina zomwe zikuchitika kumbali yake, pamene API, pazifukwa zina, sangathe kufotokoza zochitikazo, koma akhoza kungobwezera boma. Chitsanzo cha izi ndi ma API onse omangidwa pamwamba pa HTTP nthawi za WebSocket zisanafike kapena pamene zinali zosatheka pazifukwa zina kugwiritsa ntchito lusoli. Wothandizira atha kufunsa seva ya HTTP. Seva ya HTTP siyingathe kuyambitsa kulumikizana ndi kasitomala. Njira yosavuta ndiyo kufufuza seva pogwiritsa ntchito timer, koma izi zimapanga katundu wowonjezera pa seva ndi kuchedwa kwina kwapakati pa TimerInterval / 2. Kuti azungulira izi, chinyengo chotchedwa Long Polling chinapangidwa, chomwe chimaphatikizapo kuchedwetsa kuyankha kuchokera. seva mpaka Timeout itatha kapena chochitika chiti chichitike. Ngati chochitikacho chachitika, ndiye kuti chimakonzedwa, ngati sichoncho, ndiye pempholo limatumizidwanso.

while(!eventOccures && !timeoutExceeded)  {

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

Koma njira yotereyi idzakhala yowopsya mwamsanga pamene chiwerengero cha makasitomala omwe akudikirira chochitikacho chikuwonjezeka, chifukwa ... Aliyense kasitomala wotere amakhala ndi ulusi wonse kudikirira chochitika. Inde, ndipo timapeza kuchedwa kwina kwa 1ms pamene chochitikacho chikayambika, nthawi zambiri izi sizofunika, koma n'chifukwa chiyani pulogalamuyo imakhala yoipitsitsa kuposa momwe ingakhalire? Ngati tichotsa Thread.Sleep (1), ndiye pachabe tidzakweza purosesa imodzi pachimake 100% yopanda pake, ikuzungulira mopanda phindu. Pogwiritsa ntchito TaskCompletionSource mutha kupanganso code iyi mosavuta ndikuthetsa mavuto onse omwe ali pamwambapa:

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);
    }
}

Khodi iyi sinakonzekere kupanga, koma chiwonetsero chabe. Kuti mugwiritse ntchito muzochitika zenizeni, muyeneranso, osachepera, kuthana ndi vuto pamene uthenga ufika panthawi yomwe palibe amene akuyembekezera: pamenepa, njira ya AsseptMessageAsync iyenera kubwezera Ntchito yomwe yatsirizidwa kale. Ngati iyi ndiye nkhani yodziwika bwino, ndiye kuti mutha kuganiza zogwiritsa ntchito ValueTask.

Tikalandira pempho la uthenga, timapanga ndikuyika TaskCompletionSource mu dikishonale, ndiyeno timadikirira zomwe zimachitika kaye: nthawi yoikidwiratu imatha kapena uthenga walandiridwa.

ValueTask: chifukwa chiyani komanso bwanji

Ogwira ntchito async / akuyembekezera, monga wobwezera zokolola, amapanga makina a boma kuchokera ku njirayo, ndipo izi ndizopanga chinthu chatsopano, chomwe nthawi zonse chimakhala chosafunika, koma nthawi zambiri chingayambitse vuto. Mlanduwu ukhoza kukhala njira yomwe imatchedwa nthawi zambiri, tikukamba za makumi ndi mazana zikwi za mafoni pamphindi. Ngati njira yotereyi yalembedwa m'njira yoti nthawi zambiri imabwezeretsa zotsatira podutsa njira zonse zodikirira, ndiye NET imapereka chida chothandizira izi - kapangidwe ka ValueTask. Kuti timveke bwino, tiyeni tiwone chitsanzo cha ntchito yake: pali cache yomwe timapitako nthawi zambiri. Pali zinthu zina mmenemo ndiyeno timangowabweza; ngati sichoncho, ndiye timapita ku IO pang'onopang'ono kuti tikatenge. Ndikufuna kuchita izi mosagwirizana, zomwe zikutanthauza kuti njira yonseyo imakhala yosasinthika. Choncho, njira yodziwikiratu yolembera njirayo ndi iyi:

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

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

Chifukwa chofuna kukhathamiritsa pang'ono, komanso kuopa pang'ono zomwe Roslyn apanga polemba code iyi, mutha kulembanso chitsanzo ichi motere:

public Task<string> GetById(int id) {

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

Zowonadi, yankho labwino kwambiri pankhaniyi lingakhale kukhathamiritsa njira yotentha, mwachitsanzo, kupeza mtengo kuchokera ku dikishonale popanda kugawa kosafunikira ndikuyika pa GC, pomwe nthawi zina pomwe timafunikirabe kupita ku IO kuti tikapeze deta. , chirichonse chidzakhala chowonjezera / kuchotsa njira yakale:

public ValueTask<string> GetById(int id) {

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

Tiyeni tione mwatsatanetsatane kachidindo kameneka: ngati pali phindu mu cache, timapanga dongosolo, mwinamwake ntchito yeniyeni idzakulungidwa mutanthauzo. Khodi yoyimbira siyisamala kuti nambala iyi idachitidwa bwanji: ValueTask, kuchokera pamalingaliro a C # syntax, imachita chimodzimodzi ngati Ntchito yokhazikika pankhaniyi.

TaskSchedulers: kuyang'anira njira zoyambira ntchito

API yotsatira yomwe ndikufuna kuganizira ndi kalasi TaskScheduler ndi zotulukapo zake. Ndanena kale pamwambapa kuti TPL imatha kuyang'anira njira zogawira Ma Tasks kudutsa ulusi. Njira zoterezi zimafotokozedwa mu mbadwa za kalasi ya TaskScheduler. Pafupifupi njira iliyonse yomwe mungafune imapezeka mulaibulale. ParallelExtensionsExtras, yopangidwa ndi Microsoft, koma osati gawo la .NET, koma imaperekedwa ngati phukusi la Nuget. Tiyeni tione mwachidule ena mwa iwo:

  • CurrentThreadTaskScheduler - imagwira Ntchito pa ulusi womwe ulipo
  • LimitedConcurrencyLevelTaskScheduler - imachepetsa kuchuluka kwa Ntchito zomwe zimachitidwa nthawi imodzi ndi parameter N, yomwe imavomerezedwa mwa omanga
  • OrderedTaskScheduler - imatanthauzidwa ngati LimitedConcurrencyLevelTaskScheduler(1), kotero ntchito zizichitika motsatizana.
  • WorkStealingTaskScheduler - zida kuba ntchito njira yogawa ntchito. Kwenikweni ndi ThreadPool yosiyana. Amathetsa vuto kuti mu NET ThreadPool ndi gulu lokhazikika, limodzi la mapulogalamu onse, zomwe zikutanthauza kuti kudzaza kwake kapena kugwiritsidwa ntchito molakwika mu gawo limodzi la pulogalamu kungayambitse zotsatira zina. Komanso, n'zovuta kwambiri kumvetsa chomwe chimayambitsa zolakwika zoterezi. Kuti. Pakhoza kukhala kufunikira kogwiritsa ntchito osiyana WorkStealingTaskSchedulers m'madera ena a pulogalamu yomwe kugwiritsa ntchito ThreadPool kungakhale koopsa komanso kosayembekezereka.
  • QueuedTaskScheduler - amakulolani kuti mugwire ntchito molingana ndi malamulo apamzere
  • ThreadPerTaskScheduler - imapanga ulusi wosiyana pa Ntchito iliyonse yomwe imachitidwa pamenepo. Zitha kukhala zothandiza pantchito zomwe zimatenga nthawi yayitali kuti amalize.

Pali zabwino zambiri nkhani za TaskSchedulers pa Microsoft blog.

Kuti muthane bwino ndi chilichonse chokhudzana ndi Ntchito, Visual Studio ili ndi zenera la Ntchito. Pazenera ili mutha kuwona momwe ntchitoyo ikugwirira ntchito ndikudumphira ku mzere wa code womwe ukuchitidwa.

NET: Zida zogwirira ntchito ndi multithreading ndi asynchrony. Gawo 1

PLinq ndi Parallel class

Kuphatikiza pa Ntchito ndi zonse zomwe zanenedwa za iwo, pali zida ziwiri zosangalatsa mu .NET: PLinq (Linq2Parallel) ndi Parallel class. Yoyamba imalonjeza kuphatikizika kwa ntchito zonse za Linq pazingwe zingapo. Chiwerengero cha ulusi chikhoza kukhazikitsidwa pogwiritsa ntchito njira yowonjezera ya WithDegreeOfParallelism. Tsoka ilo, nthawi zambiri PLinq mumayendedwe ake osakhazikika alibe chidziwitso chokwanira chokhudza omwe ali mkati mwa gwero lanu la data kuti apereke phindu lalikulu, komano, mtengo woyesera ndi wotsika kwambiri: mumangofunika kuyimbira njira ya AsParallel kale. unyolo wa njira za Linq ndikuyesa kuyesa magwiridwe antchito. Kuphatikiza apo, ndizotheka kupereka zambiri ku PLinq za mtundu wa gwero la deta yanu pogwiritsa ntchito makina a Partitions. Mutha kuwerenga zambiri apa и apa.

Gulu la Parallel static limapereka njira zobwerezabwereza kudzera m'gulu la Foreach motsatana, kugwiritsa ntchito Lopu, ndikupereka nthumwi zingapo mu Invoke yofanana. Kuchita kwa ulusi wamakono kudzayimitsidwa mpaka mawerengedwe atsirizidwa. Chiwerengero cha ulusi chikhoza kukhazikitsidwa podutsa ParallelOptions ngati mkangano wotsiriza. Mutha kutchulanso TaskScheduler ndi CancellationToken pogwiritsa ntchito zosankha.

anapezazo

Nditayamba kulemba nkhaniyi pogwiritsa ntchito zida za lipoti langa komanso zomwe ndinasonkhanitsa panthawi ya ntchito yanga pambuyo pake, sindimayembekezera kuti padzakhala zambiri. Tsopano, pamene mkonzi wa malemba omwe ndikulemba nkhaniyi akundiuza monyoza kuti tsamba 15 lapita, ndifotokoza mwachidule zotsatira zake. Zidule zina, ma API, zida zowonera ndi misampha zidzafotokozedwa m'nkhani yotsatira.

Zotsatira:

  • Muyenera kudziwa zida zogwirira ntchito ndi ulusi, asynchrony ndi parallelism kuti mugwiritse ntchito zida zama PC amakono.
  • NET ili ndi zida zambiri zosiyanasiyana pazolinga izi
  • Sikuti onse adawonekera nthawi imodzi, kotero mutha kupeza cholowa, komabe, pali njira zosinthira ma API akale popanda kuyesetsa.
  • Kugwira ntchito ndi ulusi mu .NET kumayimiridwa ndi makalasi a Thread ndi ThreadPool
  • Njira za Thread.Abort, Thread.Interrupt, ndi Win32 API TerminateThread ndizowopsa ndipo sizovomerezeka kuti zigwiritsidwe ntchito. M'malo mwake, ndibwino kugwiritsa ntchito njira ya CancellationToken
  • Kuyenda ndi chinthu chamtengo wapatali ndipo kupezeka kwake kuli kochepa. Mikhalidwe yomwe ulusi uli wotanganidwa kudikirira zochitika ziyenera kupewedwa. Kwa izi ndikosavuta kugwiritsa ntchito kalasi ya TaskCompletionSource
  • Zida zamphamvu kwambiri komanso zapamwamba za NET zogwirira ntchito ndi kufanana ndi asynchrony ndi Ntchito.
  • Ogwiritsa ntchito a c# async/await amatsatira lingaliro la kudikirira kosatsekereza
  • Mutha kuwongolera kugawa kwa Tasks kudutsa ulusi pogwiritsa ntchito makalasi opangidwa ndi TaskScheduler
  • Mapangidwe a ValueTask atha kukhala othandiza pakukhathamiritsa njira zowotcha komanso kukumbukira-magalimoto
  • Mawindo a Visual Studio's Tasks and Threads amapereka zambiri zothandiza pakuchotsa ma code angapo kapena asynchronous
  • PLinq ndi chida chozizira, koma sichingakhale ndi chidziwitso chokwanira chokhudza gwero lanu la deta, koma izi zikhoza kukhazikitsidwa pogwiritsa ntchito njira yogawanitsa.
  • Zipitilizidwa…

Source: www.habr.com

Kuwonjezera ndemanga