NET: Ngwa eji arụ ọrụ na multithreading na asynchrony. Akụkụ 1

Ana m ebipụta akụkọ izizi na Habr, nke etinyere ntụgharị ya na ụlọ ọrụ blog posta.

Mkpa ime ihe asynchronously, na-enweghị na-eche n'ihi na ebe a na ugbu a, ma ọ bụ kewaa nnukwu ọrụ n'etiti ọtụtụ nkeji na-eme ya, adị tupu biakwa obibia nke kọmputa. Site na ọbịbịa ha, mkpa a ghọrọ ihe a na-ahụ anya nke ukwuu. Ugbu a, na 2019, m na-ede edemede a na laptọọpụ nwere 8-core Intel Core processor, nke ihe karịrị otu narị usoro na-arụ n'otu n'otu, na ọbụna eriri ndị ọzọ. N'akụkụ, enwere ekwentị na-adịghị mma, zụtara afọ ole na ole gara aga, o nwere ihe nrụpụta 8-core n'ime ụgbọ. Akụrụngwa isiokwu jupụtara na akụkọ na vidiyo ebe ndị odee ha na-enwe mmasị na smartphones flagship nke afọ a nke nwere 16-core processors. MS Azure na-enye igwe mebere igwe nwere ihe nrụpụta isi 20 yana 128 TB RAM na-erughị $2 / elekere. N'ụzọ dị mwute, ọ gaghị ekwe omume wepụ ihe kachasị na ijikwa ike a na-enweghị ike ijikwa mmekọrịta nke eri.

Usoro ihe omuma

Usoro - Ihe OS, oghere adreesị dịpụrụ adịpụ, nwere eri.
eri - ihe os, ihe kacha nta nke ogbugbu, akụkụ nke usoro, eri na-ekerịta ebe nchekwa na ihe ndị ọzọ n'etiti onwe ha n'ime usoro.
Ịme ihe - akụrụngwa OS, ikike ịme ọtụtụ usoro n'otu oge
Multi-isi - ihe onwunwe nke processor, ikike iji ọtụtụ cores maka nhazi data
Multiprocessing - ihe onwunwe nke kọmputa, ike n'otu oge na-arụ ọrụ na ọtụtụ processors anụ ahụ
Multithreading - ihe onwunwe nke usoro, ike nkesa nhazi data n'etiti ọtụtụ eri.
Myirịta - na-eme ọtụtụ omume n'otu oge n'otu oge
Asynchrony - ogbugbu nke ọrụ na-echeghị maka mmecha nhazi a; enwere ike ịhazi nsonaazụ nke ogbugbu ahụ ma emechaa.

Metaphor

Ọ bụghị nkọwa niile dị mma ma ụfọdụ chọrọ nkọwa ọzọ, yabụ m ga-agbakwunye ihe atụ gbasara isi nri nri ụtụtụ n'okwu okwu ewepụtara nke ọma. Isi nri nri ụtụtụ n'ihe atụ a bụ usoro.

Mgbe m na-akwadebe nri ụtụtụ n'ụtụtụ m (CPUAbịara m na kichin (Kọmputa). Enwere m aka 2 (Cores). Enwere ọtụtụ ngwaọrụ na kichin (IO): oven, kettle, toaster, friji. M na-agbanye gas, tinye ite frying na ya ma wụsa mmanụ n'ime ya na-echeghị ka ọ kpoo ọkụ (asynchronously, anaghị egbochi-IO-Chere), M na-ewepụ àkwá ndị ahụ n'ime refrjiraeto ma gbanye ha n'ime efere, wee jiri otu aka tie ha (Eriri #1), na nke abụọ (Eriri #2) na-ejide efere (Shared Resource). Ugbu a ọ ga-amasị m ịgbanye ketulu, mana enweghị m aka zuru oke (eri Agụụ) N'oge a, frying pan na-ekpo ọkụ (Na-edozi nsonaazụ) nke m na-awụsa ihe m kụrụ. Erutere m ite ahụ ma gbanye ya wee jiri nzuzu lelee mmiri na-esi n'ime ya (Mgbochi-IO-Chere), ọ bụ ezie na n'oge a ọ nwere ike ịsacha efere ebe ọ na-akụ omelet.

Eji m aka abụọ sie nri omelet, ma enweghị m ihe ọzọ, mana n'otu oge ahụ, n'oge a na-apịa omelet ahụ, a na-arụ ọrụ 2 n'otu oge: ịpịa omelet, jide efere ahụ, kpoo pan ahụ. CPU bụ akụkụ kachasị ngwa ngwa na kọmputa, IO bụ ihe na-emekarị ihe ọ bụla na-ebelata, ya mere, mgbe mgbe, ngwọta dị irè bụ iji ihe na-ejide CPU mgbe ị na-enweta data sitere na IO.

Na-aga n'ihu n'ihe atụ:

  • Ọ bụrụ na n'usoro ịkwadebe omelet, m ga-agbalịkwa ịgbanwe uwe, nke a ga-abụ ihe atụ nke multitasking. Nuance dị mkpa: kọmpụta dị mma na nke a karịa ndị mmadụ.
  • Otu kichin nwere ọtụtụ ndị isi nri, dịka ọmụmaatụ na ụlọ oriri na ọṅụṅụ - kọmputa multi-core.
  • Ọtụtụ ụlọ oriri na ọṅụṅụ na ụlọ oriri na ọṅụṅụ na ebe ịzụ ahịa - data center

Ngwa NET

NET dị mma na-arụ ọrụ na eri, dị ka ọtụtụ ihe ndị ọzọ. Na ụdị ọhụrụ ọ bụla, ọ na-ewebata ọtụtụ ngwa ọhụrụ maka ịrụ ọrụ na ha, ọkwa ọhụrụ nke abstraction n'elu eriri OS. Mgbe ị na-arụ ọrụ na-ewu nke abstractions, framework mmepe na-eji ụzọ na-ahapụ ohere, mgbe na-eji a elu larịị abstraction, gbadaa otu ma ọ bụ karịa ọkwa n'okpuru. Ọtụtụ mgbe nke a adịghị mkpa, n'ezie ọ na-emepe ụzọ iji egbe agbapụ onwe gị n'ụkwụ, ma mgbe ụfọdụ, n'ọnọdụ ndị na-adịghị ahụkebe, ọ nwere ike ịbụ naanị ụzọ isi dozie nsogbu na-adịghị edozi na ọkwa nke abstraction dị ugbu a. .

Site na ngwaọrụ, m na-ekwu ma interface mmemme ngwa (API) nke usoro nhazi na ngwugwu ndị ọzọ na-enye, yana ngwọta ngwanrọ dum nke na-eme ka ịchọta nsogbu ọ bụla metụtara koodu multi-threaded dị mfe.

Ịmalite eri

Klas Thread bụ klaasị kachasị na NET maka iji eriri rụọ ọrụ. Onye nrụpụta ahụ na-anabata otu n'ime ndị nnọchi anya abụọ:

  • ThreadStart - Enweghị paramita
  • ParametrizedThreadStart - nwere otu oke nke ụdị ihe.

A ga-egbu onye nnọchiteanya ahụ na eri emepụtara ọhụrụ ka ọ kpọchara usoro mmalite, ọ bụrụ na agafere ụdị ParametrizedThreadStart na onye nrụpụta, mgbe ahụ, a ga-ebufe ihe na usoro mmalite. Usoro a dị mkpa iji nyefee ozi mpaghara ọ bụla na iyi. Ọ dị mma ịmara na ịmepụta eri bụ ọrụ dị oke ọnụ, na eri ahụ n'onwe ya bụ ihe dị arọ, ma ọ dịkarịa ala n'ihi na ọ na-ekenye 1MB nke ebe nchekwa na nchịkọta ma na-achọ mmekọrịta na OS API.

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

Klas ThreadPool na-anọchite anya echiche nke ọdọ mmiri. Na NET, ọdọ mmiri eri bụ akụkụ nke injinia, ndị mmepe na Microsoft etinyela mgbalị dị ukwuu iji hụ na ọ na-arụ ọrụ nke ọma na ọnọdụ dị iche iche.

Echiche izugbe:

Site na ngwa ngwa amalitere, ọ na-emepụta ọtụtụ eri n'azụ ma na-enye ike iwere ha maka ojiji. Ọ bụrụ na a na-eji eriri eme ihe ugboro ugboro na ọnụ ọgụgụ buru ibu, ọdọ mmiri na-agbasawanye iji gboo mkpa onye na-akpọ ya. Mgbe enweghị eriri efu na ọdọ mmiri n'oge kwesịrị ekwesị, ọ ga-echere ka otu n'ime eriri ahụ laghachi azụ, ma ọ bụ mepụta nke ọhụrụ. Ọ na-esote na ọdọ mmiri eri ahụ dị mma maka omume ụfọdụ na-adịru nwa oge na adabaghị maka arụmọrụ na-agba ọsọ dị ka ọrụ n'oge ọrụ niile nke ngwa ahụ.

Iji jiri eriri sitere na ọdọ mmiri ahụ, enwere usoro QueueUserWorkItem nke na-anabata ndị nnọchi anya ụdị WaitCallback, nke nwere otu mbinye aka dị ka ParametrizedThreadStart, na parameter gafere ya na-arụ otu ọrụ ahụ.

ThreadPool.QueueUserWorkItem(...);

A na-eji usoro ọdọ mmiri eri amachaghị ama RegisterWaitForSingleObject iji hazie ọrụ IO anaghị egbochi. A ga-akpọ onye nnọchiteanya gafere na usoro a mgbe WaitHandle gafere na usoro a "wepụrụ".

ThreadPool.RegisterWaitForSingleObject(...)

NET nwere ngụ oge eri na ọ dị iche na WinForms/WPF ngụ oge na a ga-akpọ onye na-ahụ maka ya na eri ewepụtara na ọdọ mmiri.

System.Threading.Timer

Enwekwara ụzọ dị oke egwu iji zipu onye nnọchi anya maka igbu ya na eri sitere na ọdọ mmiri - usoro mbido Invoke.

DelegateInstance.BeginInvoke

Ọ ga-amasị m ileba anya nkenke na ọrụ nke enwere ike ịkpọ ọtụtụ n'ime ụzọ ndị a dị n'elu - CreateThread from Kernel32.dll Win32 API. Enwere ụzọ, ekele maka usoro nke ụzọ mpụga, ịkpọ ọrụ a. Ahụla m oku dị otú ahụ naanị otu ugboro n'ime ihe atụ jọgburu onwe ya nke koodu ihe nketa, na mkpali nke onye edemede mere kpọmkwem nke a ka bụ ihe omimi nye m.

Kernel32.dll CreateThread

Nlele na ihichapụ eri

Eriri nke gị mebere, ihe ndị ọzọ niile na ọdọ mmiri NET nwere ike ịhụ na windo Threads nke Visual Studio. Window a ga-egosipụta naanị ozi eri mgbe ngwa ahụ nọ n'okpuru debug yana na ọnọdụ nkwụsị. N'ebe a, ị nwere ike ilele aha nchịkọta na ihe ndị kacha mkpa nke eri ọ bụla, wee gbanwee debugging gaa na otu eri. N'iji ihe mbụ nke klaasị eriri, ị nwere ike ịtọ mkpa eri, nke OC na CLR ga-aghọta dị ka nkwanye mgbe ị na-eke oge nhazi n'etiti eri.

NET: Ngwa eji arụ ọrụ na multithreading na asynchrony. Akụkụ 1

Ọbá akwụkwọ Parallel Task

Ewebata Task Parallel Library (TPL) na .NET 4.0. Ugbu a ọ bụ ọkọlọtọ na ngwá ọrụ bụ isi maka ịrụ ọrụ na asynchrony. A na-ewere koodu ọ bụla nke na-eji ụzọ ochie dị ka ihe nketa. Akụkụ bụ isi nke TPL bụ klaasị Task si System.Threading.Tasks namespace. Ọrụ bụ abstraction n'elu eri. Site na ụdị asụsụ C # ọhụrụ, anyị nwetara ụzọ mara mma iji rụọ ọrụ na Tasks - ndị ọrụ async/echere. Echiche ndị a mere ka o kwe omume ịde koodu asynchronous dị ka a ga-asị na ọ dị mfe ma na-emekọrịta ihe, nke a mere ka o kwe omume ọbụna ndị na-enwechaghị nghọta nke ọrụ ime nke eri iji dee ngwa ndị na-eji ha eme ihe, ngwa ndị na-adịghị ifriizi mgbe ha na-arụ ọrụ ogologo oge. Iji async/echere bụ isiokwu maka otu ma ọ bụ ọbụna ọtụtụ akụkọ, mana m ga-agbalị ịnweta isi okwu ya n'ahịrịokwu ole na ole:

  • async bụ ihe ngbanwe nke usoro iweghachi ọrụ ma ọ bụ ihe efu
  • ma chere bụ onye ọrụ nchere Task anaghị egbochi.

Ọzọ: onye ọrụ na-echere, n'ozuzu ya (enwere ihe ndị ọzọ), ga-ahapụ eriri nke ugbu a na-eme ihe n'ihu, na mgbe ọrụ ahụ gwụchara ogbugbu ya, na eri (n'ezie, ọ ga-adị mma ikwu okwu ndị gbara ya gburugburu. , ma ọzọ na nke ahụ mechara) ga-aga n'ihu na-eme usoro ahụ n'ihu. N'ime NET, a na-emejuputa usoro a n'otu ụzọ ahụ dị ka nlọghachi azụ, mgbe usoro ederede na-atụgharị ghọọ klas dum, nke bụ igwe steeti ma nwee ike igbu ya n'ụdị dị iche iche dabere na steeti ndị a. Onye ọ bụla nwere mmasị nwere ike dee koodu ọ bụla dị mfe site na iji asynс/echere, chịkọta ma lelee mgbakọ site na iji JetBrains dotPeek na Compiler Generated Code nyeere.

Ka anyị lelee nhọrọ maka ịmalite na iji Task. N'ihe atụ koodu dị n'okpuru ebe a, anyị na-emepụta ọrụ ọhụrụ nke na-emeghị ihe ọ bụla bara uru (Eriri.Ụra(10000)), mana na ndụ n'ezie nke a kwesịrị ịbụ ụfọdụ ọrụ CPU siri ike.

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
}

A na-eji ọtụtụ nhọrọ mepụta ọrụ:

  • LongRunning bụ ihe na-egosi na ọrụ ahụ agaghị agwụ ngwa ngwa, nke pụtara na ọ nwere ike ịba uru ịtụle ịghara iburu eri site na ọdọ mmiri, ma ịmepụta ihe dị iche iche maka Ọrụ a ka ọ ghara imerụ ndị ọzọ ahụ.
  • AttachedToParent - Enwere ike ịhazi ọrụ na ọkwa. Ọ bụrụ na ejiri nhọrọ a mee ihe, mgbe ahụ, Task ahụ nwere ike ịnọ na steeti ebe ya onwe ya agwụla ma na-echere igbu ụmụ ya.
  • PreferFairness - pụtara na ọ ga-aka mma ime ihe aga-eme ezigara maka ogbugbu na mbụ tupu ndị ezitere ma emechaa. Mana nke a bụ naanị nkwanye na nsonaazụ anaghị ekwe nkwa.

Oke nke abụọ gafere na usoro a bụ CancelationToken. Iji jikwaa kagbuo ọrụ nke ọma ka ọ malitechara, koodu a na-eme ga-ejupụta na ndenye ego maka steeti CancelationToken. Ọ bụrụ na enweghị ego nlele, mgbe ahụ usoro kagbuo a na-akpọ CancelationTokenSource ihe ga-enwe ike ịkwụsị mmezu nke Task naanị tupu ya amalite.

Oke ikpeazụ bụ ihe nhazi ihe ụdị TaskScheduler. Ezubere klas a na ụmụ ụmụ ya iji jikwaa atụmatụ maka ikesa ihe aga-eme n'ofe eri; na ndabara, a ga-eme ihe omume ahụ na eri na-enweghị usoro sitere na ọdọ mmiri ahụ.

A na-etinye onye ọrụ na-echere na Task emepụtara, nke pụtara koodu e dere mgbe ọ gachara, ọ bụrụ na enwere otu, a ga-egbu ya n'otu ọnọdụ ahụ (nke a pụtara n'otu eriri) dị ka koodu tupu echee.

Usoro a ka akara dị ka async void, nke pụtara na ọ nwere ike iji onye ọrụ na-echere, mana koodu oku agaghị enwe ike ichere maka igbu ya. Ọ bụrụ na njirimara dị otú ahụ dị mkpa, mgbe ahụ, usoro ahụ ga-eweghachite Task. Ụzọ akara async efu bụ ihe a na-ahụkarị: dịka iwu, ndị a bụ ndị na-ahụ maka ihe omume ma ọ bụ ụzọ ndị ọzọ na-arụ ọrụ na ọkụ ma chefuo ụkpụrụ. Ọ bụrụ na ịchọrọ ọ bụghị naanị inye ohere iji chere ruo mgbe njedebe nke igbu egbu, ma weghachite nsonaazụ ya, mgbe ahụ ịkwesịrị iji Task.

Na Task nke usoro StartNew laghachiri, yana nke ọ bụla ọzọ, ị nwere ike ịkpọ usoro ConfigureAwait na paramita ụgha, mgbe ahụ igbu egbu mgbe echere agaghị aga n'ihu ọ bụghị na ọnọdụ ejidere, kama na nke aka ike. Ekwesịrị ime nke a mgbe ọ bụla ọnọdụ ogbugbu adịghị mkpa maka koodu ahụ mgbe ichere. Nke a bụkwa nkwanye sitere n'aka MS mgbe ị na-ede koodu nke a ga-ebunye ngwugwu n'ọbá akwụkwọ.

Ka anyị chebakwuoro otu ị ga-esi chere ka arụcha ọrụ. N'okpuru bụ ihe atụ nke koodu, na-ekwu na mgbe a na-atụ anya na-emere ọnọdụ nke ọma na mgbe a na-eme ya na ọnọdụ adịghị mma.

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
}

N'ihe atụ nke mbụ, anyị na-echere ọrụ ahụ ka ọ rụchaa na-enweghị igbochi eriri oku; anyị ga-alaghachi na nhazi nsonaazụ naanị mgbe ọ dịlarị, ruo mgbe ahụ, eriri oku na-ahapụ ya na ngwaọrụ nke ya.

Na nhọrọ nke abụọ, anyị na-egbochi eriri oku ahụ ruo mgbe agbakọọ nsonaazụ nke usoro ahụ. Nke a bụ ihe ọjọọ ọ bụghị naanị n'ihi na anyị ji eri, ndị dị otú ahụ a bara uru akụ nke mmemme, na mfe idleness, kamakwa n'ihi na ọ bụrụ na koodu nke usoro na anyị na-akpọ nwere echere, na mmekọrịta onodu chọrọ ịlaghachi na oku eri mgbe. chere, mgbe ahụ, anyị ga-enweta a deadlock : The oku na-akpọ eri na-echere n'ihi na nke asynchronous usoro na-agbakọọ, asynchronous usoro na-agbalị n'efu na-aga n'ihu na-egbu ya na-akpọ eri.

Mwepu ọzọ nke ụzọ a bụ njikwa njehie dị mgbagwoju anya. Nke bụ eziokwu bụ na njehie dị na koodu asynchronous mgbe ị na-eji async/echere dị mfe ijikwa - ha na-eme otu ihe ahụ dị ka a ga-asị na koodu ahụ bụ mmekọrịta. Ọ bụrụ na anyị etinye exorcism nchere synchronous na ọrụ, ewepụrụ mbụ ga-aghọ AggregateException, i.e. Iji jikwaa ewepu, ị ga-enyocha ụdị InnerException wee dee agbụ n'onwe gị n'ime otu ngọngọ ma ọ bụ jiri nwude mgbe arụrụ ya, kama ịnya njide nke maara nke ọma na ụwa C #.

Ihe atụ nke atọ na nke ikpeazụ bụkwa akara ọjọọ maka otu ihe kpatara ya ma nwee otu nsogbu niile.

Usoro mgbe ọ bụla na mgbe niile dị oke mma maka ichere otu ọrụ; ha na-ekekọta otu ọrụ n'ime otu, nke ga-agba ọkụ ma ọ bụrụ na ebido ọrụ sitere na otu ahụ, ma ọ bụ mgbe ha niile mechara ogbugbu ha.

eriri nkwụsị

Maka ihe dị iche iche, ọ nwere ike ịdị mkpa ịkwụsị mmiri ahụ mgbe ọ malitechara. Enwere ụzọ dị iche iche isi mee nke a. Klas Thread nwere ụzọ aha abụọ dabara adaba: Wepu и Kwụsịtụ. Nke mbụ bụ nke ukwuu adịghị atụ aro maka ojiji, n'ihi na mgbe akpọchara ya n'oge ọ bụla na-enweghị usoro, n'oge nhazi nke ntụziaka ọ bụla, a ga-atụfu ihe dị iche ThreadAbortedException. Ị naghị atụ anya na a ga-atụba ihe dị otú ahụ mgbe ị na-emewanye mgbanwe ọnụọgụ ọnụọgụ ọ bụla, nri? Na mgbe ị na-eji usoro a, nke a bụ ezigbo ọnọdụ. Ọ bụrụ na ịchọrọ igbochi CLR iwepụta ihe dị otú ahụ na mpaghara ụfọdụ nke koodu, ị nwere ike kechie ya na oku. Eriri.BeginCriticalRegion, Eriri.EndCriticalRegion. Koodu ọ bụla edere na ngọngọ ikpeazụ ka etinyere na oku dị otú ahụ. N'ihi nke a, n'ime omimi nke koodu nhazi ị nwere ike ịchọta ngọngọ na-anwale efu, ma ọ bụghị ihe efu n'ikpeazụ. Microsoft na-akụda usoro a nke ukwuu nke na ha etinyeghị ya na isi .net.

Usoro nkwụsịtụ na-arụ ọrụ karịa amụma. Ọ nwere ike ịkwụsị eri ahụ ma wezuga ya ThreadInterruptedException naanị n'oge ndị ahụ mgbe eri ahụ nọ na ọnọdụ nchere. Ọ na-abanye na steeti a ka ọ na-ekudo ka ọ na-eche WaitHandle, mkpọchi, ma ọ bụ mgbe ọ kpọchara eriri.Sleep.

Nhọrọ abụọ a akọwara n'elu dị njọ n'ihi enweghị atụ ha. Ihe ngwọta bụ iji nhazi CancellationToken na klas CancelationTokenSource. Isi ihe bụ nke a: emepụtara klaasị CancelationTokenSource na naanị onye nwere ya nwere ike kwụsị ọrụ ahụ site na ịkpọ usoro ahụ. Kagbuo. Naanị CancelationToken ka a na-enyefe n'ọrụ ahụ n'onwe ya. Ndị nwe CancelationToken enweghị ike ịkagbu ọrụ ahụ n'onwe ha, mana ha nwere ike lelee ma akagbuola ọrụ ahụ. Enwere ụlọ Boolean maka nke a Arịrịọ kagbuo na usoro TụfuỌ bụrụ Kagbuo Arịrịọ. Nke ikpeazụ ga-atụfu mwepu TaskCancelled Exception Ọ bụrụ na a na-akpọ usoro ịkagbu na ihe atụ CancellationToken na-atụgharị. Ma nke a bụ usoro m na-akwado iji. Nke a bụ nkwalite karịa nhọrọ ndị gara aga site n'inweta njikwa zuru oke n'oge enwere ike iwepụ ọrụ ewepu.

Nhọrọ kacha njọ maka ịkwụsị eri bụ ịkpọ Win32 API TerminateThread ọrụ. Omume nke CLR mgbe ịkpọchara ọrụ a nwere ike bụrụ ihe a na-atụghị anya ya. Na MSDN, edere ihe ndị a gbasara ọrụ a: "TerminateThread bụ ọrụ dị ize ndụ nke ekwesịrị iji naanị n'ọnọdụ kacha njọ. "

Ịtụgharị API nketa ka ọ bụrụ ọrụ dabere na iji usoro FromAsync

Ọ bụrụ na ị nwere ihu ọma ịrụ ọrụ nke malitere mgbe ewebatara Ọrụ wee kwụsị ịkpata ụjọ dị jụụ maka ọtụtụ ndị mmepe, mgbe ahụ ị gaghị emeso ọtụtụ API ochie, ma ndị nke atọ na ndị otu gị. emekpaala n'oge gara aga. N'ụzọ dị mma, ndị otu NET Framework lekọtara anyị, ọ bụ ezie na ikekwe ebumnuche bụ ilekọta onwe anyị. Ọ bụrụ na ọ nwere ike, NET nwere ọtụtụ ngwaọrụ maka ịtụgharị koodu n'enweghị mgbu nke edere na mmemme mmemme ochie asynchronous na-abịaru nso nke ọhụrụ. Otu n'ime ha bụ usoro FromAsync nke TaskFactory. N'ihe atụ koodu dị n'okpuru, m na-ekechi usoro async ochie nke klaasị WebRequest n'ime ọrụ site na iji usoro a.

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

Nke a bụ naanị ihe atụ na o yighị ka ị ga-eme nke a na ụdị arụnyere n'ime ya, mana ọrụ ochie ọ bụla na-ejupụta na ụzọ BeginDoSomething na-eweghachite IAsyncResult na EndDoSomething ụzọ na-enweta ya.

Tụgharịa API ihe nketa ka ọ bụrụ ọrụ dabere na iji klaasị TaskCompletionSource

Ngwá ọrụ ọzọ dị mkpa ị ga-atụle bụ klas TaskCompletionSource. N'ihe gbasara ọrụ, ebumnuche na ụkpụrụ nke ọrụ, ọ nwere ike ịdịtụ icheta usoro RegisterWaitForSingleObject nke klaasị ThreadPool, nke m dere gbasara ya n'elu. Iji klaasị a, ị nwere ike kechie API ochie asynchronous n'ụzọ dị mfe na n'ụzọ dabara adaba na Ọrụ.

Ị ga-ekwu na m ekwuola maka usoro FromAsync nke klaasị TaskFactory ezubere maka ebumnuche ndị a. N'ebe a, anyị ga-echeta akụkọ dum gbasara mmepe nke ụdị asynchronous na .net nke Microsoft nyere n'ime afọ 15 gara aga: tupu Task-Based Asynchronous Pattern (TAP), e nwere Asynchronous Programming Pattern (APP), nke. bụ banyere ụzọ MaliteIhe na-alọghachi IAsyncresult na usoro ọgwụgwụDoSomething na-anabata ya na maka ihe nketa nke afọ ndị a, usoro FromAsync zuru oke, mana ka oge na-aga, e ji ihe omume Asynchronous Asynchronous dochie ya.EP), nke chere na a ga-ebuli ihe omume mgbe arụrụ ọrụ asynchronous rụchara.

TaskCompletionSource zuru oke maka ikechi ihe aga-eme na API ihe nketa wuru gburugburu ụdị mmemme ahụ. Ihe kachasị mkpa nke ọrụ ya bụ nke a: ihe nke klas a nwere ihe onwunwe ọha na eze nke ụdị Task, ọnọdụ nke nwere ike ịchịkwa site na SetResult, SetException, wdg usoro nke TaskCompletionSource klas. N'ebe etinyere onye ọrụ na-echere n'ọrụ a, a ga-eme ya ma ọ bụ daa ma wezuga ya dabere na usoro etinyere na TaskCompletionSource. Ọ bụrụ na ọ ka edoghị anya, ka anyị leba anya n'ihe atụ koodu a, ebe ụfọdụ EAP API ochie na-etinye n'ọrụ site na iji TaskCompletionSource: mgbe ihe omume ahụ gbara ọkụ, a ga-ebufe Task ahụ na steeti Emechara, yana usoro etinyere onye ọrụ na-echere. na ọrụ a ga-amaliteghachi ogbugbu ya mgbe ọ natara ihe ahụ akpata.

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

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

    result completionSource.Task;
}

Ndụmọdụ na aghụghọ TaskCompletionSource

Ichichi API ochie abụghị ihe niile enwere ike iji TaskCompletionSource mee. Iji klaasị a na-emepe ohere na-atọ ụtọ nke imepụta API dị iche iche na Ọrụ ndị eri anaghị ejide. Na iyi, dị ka anyị na-echeta, bụ ihe dị oké ọnụ ahịa akụ na ọnụ ọgụgụ ha na-ejedebeghị (tumadi site na ego nke RAM). Enwere ike nweta mmachi a n'ụzọ dị mfe site n'ịmepụta, dịka ọmụmaatụ, ngwa weebụ eburu ibu nwere mgbagha azụmahịa. Ka anyị tụlee ohere ndị m na-ekwu maka mgbe anyị na-emejuputa aghụghọ dị ka Long-Polling.

Na nkenke, isi ihe aghụghọ ahụ bụ nke a: ịkwesịrị ịnata ozi sitere na API banyere ụfọdụ ihe na-eme n'akụkụ ya, ebe API, n'ihi ihe ụfọdụ, enweghị ike ịkọ ihe omume ahụ, ma ọ nwere ike ịlaghachi na steeti ahụ. Ihe atụ nke ndị a bụ API niile arụnyere n'elu HTTP tupu oge WebSocket ma ọ bụ mgbe ọ na-agaghị ekwe omume maka ihe ụfọdụ iji teknụzụ a. Onye ahịa nwere ike jụọ ihe nkesa HTTP. Ihe nkesa HTTP enweghị ike ịmalite nkwurịta okwu n'onwe ya na onye ahịa. Ngwọta dị mfe bụ ịme ntuli aka nke ihe nkesa site na iji ngụ oge, ma nke a na-emepụta ihe mgbakwunye na ihe nkesa na nkwụsịtụ ọzọ na nkezi TimerInterval / 2. Iji nweta gburugburu nke a, e mepụtara aghụghọ a na-akpọ Long Polling, nke gụnyere igbu oge nzaghachi site na ihe nkesa ahụ ruo mgbe oge ga-agwụ ma ọ bụ ihe omume ga-eme. Ọ bụrụ na ihe omume ahụ mere, mgbe ahụ, a na-edozi ya, ọ bụrụ na ọ bụghị, mgbe ahụ, a ga-eziga arịrịọ ahụ ọzọ.

while(!eventOccures && !timeoutExceeded)  {

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

Ma ngwọta dị otú ahụ ga-abụ ihe egwu ozugbo ọnụ ọgụgụ ndị ahịa na-echere ihe omume ahụ na-abawanye, n'ihi na ... Onye ọ bụla dị otú ahụ ahịa nwere dum eri na-eche ihe omume. Ee, anyị na-enwetakwa igbu oge 1ms ọzọ mgbe ihe omume ahụ kpalitere, ọtụtụ mgbe nke a adịghị mkpa, mana gịnị kpatara na ngwanrọ ahụ ka njọ karịa ka ọ nwere ike ịdị? Ọ bụrụ na anyị ewepụ Thread.Sleep(1), mgbe ahụ, n'efu, anyị ga-ebu otu processor isi 100% na-abaghị uru, na-atụgharị na okirikiri na-abaghị uru. Iji TaskCompletionSource ị nwere ike megharịa koodu a ngwa ngwa wee dozie nsogbu niile akọwapụtara n'elu:

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

Koodu a abụghị mmepụta-njikere, kama ọ bụ naanị ngosi. Iji jiri ya mee ihe n'ezie, ị ga-achọkwa, opekempe, iji dozie ọnọdụ ahụ mgbe ozi rutere n'oge ọ na-adịghị onye na-atụ anya ya: na nke a, usoro AsseptMessageAsync kwesịrị iweghachi ọrụ emechala. Ọ bụrụ na nke a bụ ikpe a na-ahụkarị, mgbe ahụ ị nwere ike iche maka iji ValueTask.

Mgbe anyị nwetara arịrịọ maka ozi, anyị na-emepụta ma tinye TaskCompletionSource n'ime akwụkwọ ọkọwa okwu, wee chere ihe ga-eme na mbụ: oge ​​a kapịrị ọnụ agwụ ma ọ bụ nata ozi.

ValueTask: ihe kpatara na otu

Ndị na-arụ ọrụ async / na-echere, dị ka onye ọrụ nlọghachi nke mkpụrụ, na-emepụta igwe steeti site na usoro ahụ, nke a bụ ịmepụta ihe ọhụrụ, nke fọrọ nke nta ka ọ bụrụ mgbe niile adịghị mkpa, ma n'ọnọdụ ndị na-adịghị ahụkebe ọ nwere ike ịmepụta nsogbu. Ikpe a nwere ike ịbụ usoro a na-akpọ n'ezie mgbe mgbe, anyị na-ekwu maka iri iri na otu narị puku oku kwa nkeji. Ọ bụrụ na edere usoro dị otú ahụ n'ụzọ na n'ọtụtụ ọnọdụ ọ na-eweghachi nsonaazụ site na ịgafe ụzọ niile echere, mgbe ahụ .NET na-enye ngwá ọrụ iji kwalite nke a - ValueTask Ọdịdị. Iji mee ka o doo anya, ka anyị leba anya n'ihe atụ nke ojiji ya: enwere oghere nke anyị na-agakarị. Enwere ụfọdụ ụkpụrụ na ya wee weghachi ha naanị; ọ bụrụ na ọ bụghị, anyị ga-aga na IO nwayọ iji nweta ha. Achọrọ m ime nke ikpeazụ n'enweghị ihe ọ bụla, nke pụtara na usoro ahụ dum ga-abụ asynchronous. Ya mere, ụzọ doro anya isi dee usoro a bụ:

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

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

N'ihi ọchịchọ ịkwalite ntakịrị, yana ntakịrị egwu ihe Roslyn ga-emepụta mgbe ị na-achịkọta koodu a, ị nwere ike idegharị ihe atụ a dị ka ndị a:

public Task<string> GetById(int id) {

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

N'ezie, ihe ngwọta kachasị mma na nke a ga-abụ ịkwalite ụzọ na-ekpo ọkụ, ya bụ, ịnweta uru site na akwụkwọ ọkọwa okwu na-enweghị oke ọ bụla na-adịghị mkpa na ibu na GC, ebe n'ọnọdụ ndị ahụ na-adịghị ahụkebe mgbe anyị ka kwesịrị ịga IO maka data. , ihe niile ga-anọgide na gbakwunyere / mwepu ụzọ ochie:

public ValueTask<string> GetById(int id) {

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

Ka anyị lebakwuo anya na mpempe koodu a: ọ bụrụ na ọ bara uru na cache, anyị na-emepụta ihe owuwu, ma ọ bụghị ya, a ga-etinye ezigbo ọrụ ahụ n'ime ihe bara uru. Koodu ịkpọ oku ahụ achọghị ịma ụzọ e mere koodu a na: ValueTask, site na echiche C # syntax, ga-eme otu ihe ahụ dị ka ọrụ a na-eme mgbe niile na nke a.

TaskSchedulers: ijikwa atụmatụ mmalite ọrụ

API na-esote nke m ga-achọ ịtụle bụ klas Ihe nhazi ọrụ na usoro ya. Ekwuru m n'elu na TPL nwere ikike ijikwa atụmatụ maka ikesa ọrụ n'ofe eri. A kọwapụtara atụmatụ ndị dị otú ahụ na ụmụ klaasị TaskScheduler. Enwere ike ịchọta atụmatụ ọ bụla ị ga-achọ n'ọbá akwụkwọ. ParallelExtension Extras, nke Microsoft mepụtara, ma ọ bụghị akụkụ nke NET, mana ọ bụ ngwungwu Nuget. Ka anyị leba anya ná nkenke ụfọdụ n’ime ha:

  • Ihe nhazi ọrụ nke ugbu a - na-arụ ọrụ na eri dị ugbu a
  • Usoro nhazi ọkwa ọkwa dị oke - na-amachi ọnụ ọgụgụ ọrụ ndị a na-eme n'otu oge site na paramita N, nke a nabatara na onye nrụpụta.
  • Usoro nhazi ọrụ enyere iwu - akọwara dị ka LimitedConcurrencyLevelTaskScheduler(1), yabụ aga-eme ihe aga-eme n'usoro.
  • Ihe nhazi ọrụ izu ohi - arụ ọrụ ọrụ-ohi ụzọ maka nkesa ọrụ. N'ezie ọ bụ ThreadPool dị iche. Na-edozi nsogbu ahụ na .NET ThreadPool bụ klaasị static, otu maka ngwa niile, nke pụtara na ibubiga ya ókè ma ọ bụ iji ya eme ihe na-ezighi ezi n'otu akụkụ nke mmemme nwere ike ibute nsonaazụ na nke ọzọ. Ọzọkwa, ọ na-esi nnọọ ike ịghọta ihe kpatara ntụpọ ndị dị otú ahụ. Nke ahụ. Enwere ike ịnwe mkpa iji WorkStealingTaskSchedulers dị iche na akụkụ nke mmemme ebe iji ThreadPool nwere ike bụrụ ihe ike na enweghị atụ.
  • QueuedTask Scheduler - na-enye gị ohere ịrụ ọrụ dịka iwu kwụ n'ahịrị
  • ThreadPerTaskScheduler - na-emepụta eriri dị iche iche maka ọrụ ọ bụla a na-eme na ya. Nwere ike ịba uru maka ọrụ ndị na-ewe ogologo oge na-enweghị atụ iji rụchaa.

Enwere nkọwa zuru oke otu isiokwu gbasara TaskSchedulers na blọọgụ microsoft.

Maka nbibi dị mma nke ihe niile metụtara Ọrụ, Visual Studio nwere windo ọrụ. Na mpio a, ị nwere ike ịhụ ọnọdụ ọrụ dị ugbu a wee wụba na ahịrị koodu na-eme ugbu a.

NET: Ngwa eji arụ ọrụ na multithreading na asynchrony. Akụkụ 1

PLinq na Klas Parallel

Na mgbakwunye na ọrụ na ihe niile ekwuru banyere ha, enwere ngwaọrụ abụọ na-atọ ụtọ na NET: PLinq (Linq2Parallel) na klas Parallel. Nke mbụ kwere nkwa mmezu nke ọrụ Linq niile n'ọtụtụ eriri. Enwere ike ịhazi ọnụọgụ nke eri site na iji usoro ndọtị WithDegreeOfParallelism. N'ụzọ dị mwute, ọtụtụ mgbe PLinq na ọnọdụ ndabara ya enweghị ozi zuru ezu banyere internals nke isi iyi data gị iji nye uru ọsọ ọsọ, n'aka nke ọzọ, ọnụ ahịa ịnwale dị ala: naanị ị ga-akpọ usoro AsParallel tupu. Agbụ nke ụzọ Linq na-agba ọsọ ule arụmọrụ. Ọzọkwa, ọ ga-ekwe omume ịnyefe PLinq ozi ndị ọzọ gbasara ọdịdị data gị site na iji usoro nkebi. Ị nwere ike ịgụkwu ebe a и ebe a.

Klas static Parallel na-enye ụzọ maka ịkọgharị site na mkpokọta Foreach n'otu aka ahụ, na-eme maka loop, na igbu ọtụtụ ndị nnọchite anya n'otu aka ahụ. A ga-akwụsị mmezu nke eri dị ugbu a ruo mgbe agbakọchara. Enwere ike ịhazi ọnụọgụ nke eri site na ịgafe ParallelOptions dị ka arụmụka ikpeazụ. Ị nwekwara ike ezipụta TaskScheduler na CancelationToken site na iji nhọrọ.

Nchoputa

Mgbe m malitere ide akụkọ a dabere n'ihe akụkọ m na ozi m nakọtara n'oge ọrụ m mgbe ọ gasịrị, atụghị m anya na a ga-enwe ọtụtụ n'ime ya. Ugbu a, mgbe onye ndezi ederede nke m na-ede akụkọ a n'ụzọ mkparị gwara m na ibe 15 agaala, m ga-achịkọta nsonaazụ nwa oge. Aghụghọ ndị ọzọ, API, ngwaọrụ anya na ọnyà ga-ekpuchi n'isiokwu na-esote.

Mkpebi:

  • Ịkwesịrị ịma ngwaọrụ maka ịrụ ọrụ na eri, asynchrony na parallelism iji jiri akụrụngwa nke PC ọgbara ọhụrụ.
  • NET nwere ọtụtụ ngwaọrụ dị iche iche maka ebumnuche ndị a
  • Ọ bụghị ha niile pụtara otu oge, yabụ ị nwere ike ịhụ ndị nketa, agbanyeghị, enwere ụzọ isi gbanwee API ochie na-enweghị nnukwu mbọ.
  • Iji eriri na-arụ ọrụ na NET bụ klaasị Thread na ThreadPool nọchitere anya ya
  • The Thread.Abort, Thread.Interrupt, and Win32 API Nkwụsị usoro usoro ntanetị dị ize ndụ ma anaghị akwado ya maka ojiji. Kama, ọ ka mma iji usoro CancelationToken
  • Flow bụ akụ bara uru yana ọkọnọ ya nwere oke. Ọnọdụ ebe eri na-arụsi ọrụ ike na-eche ihe omume kwesịrị izere. Maka nke a ọ dị mma iji klaasị TaskCompletionSource
  • Ngwa NET kachasị ike na nke dị elu maka ịrụ ọrụ na myirịta na asynchrony bụ Ọrụ.
  • Ndị ọrụ c # async/echere na-emejuputa echiche nke ichere anaghị egbochi
  • Ị nwere ike ijikwa klaasị sitere TaskScheduler jikwaa nkesa nke ihe aga-eme n'ofe eri
  • Ọdịdị ValueTask nwere ike ịba uru n'ịkwalite ụzọ ọkụ na ebe nchekwa-ọzọ
  • Ihe aga-eme na string nke Visual Studio na-enye ọtụtụ ozi bara uru maka imezi koodu multi-threaded ma ọ bụ asynchronous.
  • PLinq bụ ngwá ọrụ dị mma, mana ọ nwere ike ọ gaghị enwe ozi zuru ezu gbasara ebe data gị, mana enwere ike idozi nke a site na iji usoro nkewa.
  • Ka ga-aga n'ihu…

isi: www.habr.com

Tinye a comment