.NET: Izixhobo zokusebenza nge-multithreading kunye ne-asynchrony. Icandelo loku-1

Ndipapasha inqaku lokuqala kuHabr, ukuguqulelwa kwalo kufakwe kwishishini iposti yebhlog.

Isidingo sokwenza into engahambelaniyo, ngaphandle kokulinda isiphumo apha kwaye ngoku, okanye ukwahlula umsebenzi omkhulu phakathi kweeyunithi ezininzi eziyenzayo, yayikhona ngaphambi kokuvela kweekhompyuter. Ngokufika kwabo, le mfuno yaba yinto ebonakalayo kakhulu. Ngoku, ngo-2019, ndibhala eli nqaku kwilaptop ene-8-core Intel Core processor, apho iinkqubo ezingaphezu kwekhulu zisebenza ngokuhambelanayo, kunye nemisonto engaphezulu. Kufuphi, kukho ifowuni encinci, ethengwe kwiminyaka embalwa eyadlulayo, ine-8-core processor ebhodini. Izixhobo ezinemixholo zigcwele amanqaku kunye neevidiyo apho ababhali bazo bezincoma ii-smartphones zalo nyaka ezibonisa iiprosesa ezingundoqo ezili-16. I-MS Azure inikezela ngomatshini obonakalayo kunye neprosesa ye-core 20 kunye ne-128 TB RAM ngaphantsi kwe-$ 2 / iyure. Ngelishwa, akunakwenzeka ukukhupha ubuninzi kunye nokubopha la mandla ngaphandle kokukwazi ukulawula intsebenziswano yeentambo.

I sigama

Inkqubo - Into ye-OS, indawo yedilesi esecaleni, iqulethe imisonto.
Umsonto -into ye-OS, eyona yunithi incinci yokubulawa, inxalenye yenkqubo, imisonto yabelana ngememori kunye nezinye izibonelelo phakathi kwabo ngaphakathi kwenkqubo.
Ukwenza imisebenzi emininzi -Ipropathi ye-OS, ukukwazi ukuqhuba iinkqubo ezininzi ngaxeshanye
Multi-core - ipropathi yeprosesa, ukukwazi ukusebenzisa ii-cores ezininzi zokucubungula idatha
Multiprocessing -ipropathi yekhompyuter, ukukwazi ukusebenza ngaxeshanye kunye neeprosesa ezininzi ngokwasemzimbeni
Multithreading - ipropathi yenkqubo, ukukwazi ukusasaza ukusetyenzwa kwedatha phakathi kwemicu emininzi.
Ukufana - ukwenza iintshukumo ezininzi ngokwasemzimbeni ngaxeshanye ngeyunithi yexesha
Asynchrony -ukwenziwa komsebenzi ngaphandle kokulinda ukugqityezelwa kolu cwangciso, isiphumo sokwenziwa komsebenzi sinokusetyenzwa kamva.

Imifanekiso

Ayizizo zonke iinkcazo ezilungileyo kwaye ezinye zifuna ingcaciso eyongezelelweyo, ngoko ke ndiza kongeza isikweko malunga nokupheka isidlo sakusasa kwisigama esaziswa ngokusesikweni. Ukupheka isidlo sakusasa kulo mzekeliso yinkqubo.

Ngelixesha ndilungisa isidlo sakusasa ekuseni nda (ICPUNdifike e kitchen(Ikhompyuter). ndinezandla ezi-2 (umphakathi). Kukho inani lezixhobo ekhitshini (IO): i-oveni, iketile, itoaster, ifriji. Ndilayite I gas ndabeka I frying pan ndagalela I oil ndingalindanga noba itshise.ngokulandelelanayo, Ukungathinteli-IO-Linda), ndikhupha amaqanda efrijini kwaye ndiwaphule kwisitya, ndize ndiwabethe ngesandla esinye (Umsonto#1), kunye neyesibini (Umsonto#2) ubambe ipleyiti (iSixhobo ekwabelwana ngaso). Ngoku ndingathanda ukuvula iketile, kodwa andinazo izandla zaneleyo (Umsonto Indlala) Ngeli xesha, i-pan yokucoca iyatshisa (Ukucubungula umphumo) apho ndigalela into endiyibethe ngayo. Ndifike eketile ndiyilayite ndijonge ngobubhanxa amanzi ebila kuyo (Ukuvala-IO-Yima), nangona ngeli xesha wayenokuhlamba isitya apho wayebetha khona i-omelet.

Ndipheke i-omelet ndisebenzisa izandla ezi-2 kuphela, kwaye andinayo ngaphezulu, kodwa kwangaxeshanye, ngexesha lokubetha i-omelet, kwenziwa imisebenzi emi-3 ngexesha elinye: ukubetha i-omelet, ukubamba ipleyiti, ukufudumeza ipani yokuqhotsa. I-CPU yeyona ndawo ikhawulezayo yekhompyuter, i-IO yeyona nto idla ngokucotha yonke into, ngokufuthi isisombululo esisebenzayo kukuhlala kwi-CPU ngento ngelixa ufumana idatha evela kwi-IO.

Ukuqhubela phambili isikweko:

  • Ukuba kwinkqubo yokulungiselela i-omelet, ndiza kuphinda ndizame ukutshintsha iimpahla, oku kuya kuba ngumzekelo we-multitasking. I-nuance ebalulekileyo: iikhomputha zingcono kakhulu kule nto kunabantu.
  • Ikhitshi elinabapheki abaninzi, umzekelo kwindawo yokutyela - ikhompyuter eninzi.
  • Iindawo zokutyela ezininzi kwindawo yokutya kwindawo yokuthenga - iziko ledatha

.NET izixhobo

.NET ilungile ekusebenzeni ngemisonto, njengezinye izinto ezininzi. Ngenguqulelo entsha nganye, yazisa ngakumbi nangakumbi izixhobo ezitsha zokusebenza kunye nazo, iileya ezintsha zokutsalwa phezu kwemisonto ye-OS. Xa besebenza kunye nokwakhiwa kwee-abstractions, abaphuhlisi besakhelo basebenzisa indlela eshiya ithuba, xa usebenzisa i-abstraction ephezulu, ukuhla kwinqanaba elinye okanye ngaphezulu. Amaxesha amaninzi oku akuyomfuneko, enyanisweni ivula umnyango wokuzidubula unyawo lwakho ngompu, kodwa ngamanye amaxesha, kwiimeko ezinqabileyo, inokuba yodwa indlela yokusombulula ingxaki engasonjululwanga kwinqanaba langoku lokukhupha. .

Ngezixhobo, ndithetha zombini i-interfaces yeprogram yesicelo (i-APIs) ezibonelelwa ngesakhelo kunye neephakheji zeqela lesithathu, kunye nezisombululo zesofthiwe ezipheleleyo ezenza lula ukukhangela naziphi na iingxaki ezinxulumene nekhowudi enemisonto emininzi.

Ukuqala umsonto

Iklasi yomsonto yeyona klasi isisiseko kwi.NET yokusebenza ngemisonto. Umakhi wamkela omnye wabathunywa ababini:

  • ThreadStart - Akukho parameters
  • ParametrizedThreadStart - kunye neparameter enye yohlobo lwento.

Umthunywa uza kuphunyezwa kumsonto owenziwe ngokutsha emva kokubiza indlela yokuQalisa Ukuba umthunywa wohlobo lweParametrizedThreadStart ugqithiselwe kumakhi, into kufuneka igqithiselwe kwindlela yokuQalisa. Le ndlela yokusebenza iyafuneka ukudlulisa naluphi na ulwazi lwendawo kumsinga. Kuyafaneleka ukuba uqaphele ukuba ukudala intambo yinto ebiza kakhulu, kwaye intambo ngokwayo yinto enzima, ubuncinane kuba yabela i-1MB yememori kwi-stack kwaye idinga ukusebenzisana ne-OS API.

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

Iklasi ye-ThreadPool imele ingcamango yedama. Kwi-NET, idama lomsonto liqhekeza lobunjineli, kwaye abaphuhlisi beMicrosoft babeke umzamo omkhulu wokuqinisekisa ukuba isebenza ngokugqibeleleyo kwiimeko ezahlukeneyo.

Ingqiqo ngokubanzi:

Ukusukela oko isicelo siqala, yenza imisonto emininzi kwindawo ebekelwe ngasemva kwaye ibonelela ngokukwazi ukuyithatha isetyenziswe. Ukuba imisonto isetyenziswa rhoqo kwaye ngamanani amakhulu, ichibi liyakhula ukuhlangabezana neemfuno zomnxebi. Xa kungekho misonto yasimahla echibini ngexesha elifanelekileyo, iya kulinda enye yeentambo ukuba ibuye, okanye idale entsha. Oku kulandela ukuba i-thread pool ilungile kwizenzo zexesha elifutshane kwaye ayifanelekanga kakuhle kwimisebenzi eqhuba njengeenkonzo kulo lonke umsebenzi wesicelo.

Ukusebenzisa intambo esuka echibini, kukho indlela ye-QueueUserWorkItem eyamkela umthunywa wohlobo lwe-WaitCallback, onotyikityo olufana nolwe-ParametrizedThreadStart, kwaye iparameter egqithiselwe kuyo yenza umsebenzi ofanayo.

ThreadPool.QueueUserWorkItem(...);

Indlela yokudibanisa intambo eyaziwa kancinci RegisterWaitForSingleObject isetyenziselwa ukuququzelela imisebenzi ye-IO engavaleliyo. Umthunywa ogqithiselwe kule ndlela uya kubizwa xa i-WaitHandle idluliselwe kwindlela "Ikhutshwe".

ThreadPool.RegisterWaitForSingleObject(...)

.NET inesibali-xesha sentambo kwaye iyahluka kwii-WinForms/WPF timers kuba umphathi wayo uya kubizwa kwintambo ethathwe echibini.

System.Threading.Timer

Kukwakho indlela engaqhelekanga yokuthumela umthunywa ukuba aphumeze kumsonto osuka echibini-indlela ye-BeginInvoke.

DelegateInstance.BeginInvoke

Ndingathanda ukuhlala ngokufutshane kumsebenzi apho uninzi lweendlela ezingentla zinokuthiwa - CreateThread from Kernel32.dll Win32 API. Kukho indlela, enkosi kwindlela yeendlela zangaphandle, ukubiza lo msebenzi. Ndibone umnxeba onjalo kanye kuphela kumzekelo ombi wekhowudi yelifa, kwaye inkuthazo yombhali owenze kanye le nto iseyimfihlakalo kum.

Kernel32.dll CreateThread

UkuJonga kunye nokulungiswa kweMisonto

Imisonto eyenziwe nguwe, onke amacandelo eqela lesithathu, kunye ne-NET pool inokujongwa kwiMisonto yefestile yeVisual Studio. Le festile iya kubonisa kuphela ulwazi lomsonto xa isicelo siphantsi kolungiso kwaye sikwimowudi yoKwaphula. Apha ungajonga ngokufanelekileyo amagama emfumba kunye nezinto eziphambili zomsonto ngamnye, kwaye utshintshe ukulungisa ingxaki kumsonto othile. Ukusebenzisa ipropati ePhambili yeklasi ye-Tread, unokuseta okuphambili kwentambo, apho i-OC kunye ne-CLR iya kuqonda njengengcebiso xa uhlula ixesha lokuqhuba phakathi kwemisonto.

.NET: Izixhobo zokusebenza nge-multithreading kunye ne-asynchrony. Icandelo loku-1

UmSebenzi weThala leencwadi eliFanayo

Ithala leencwadi leTask Parallel (TPL) laziswa kwi.NET 4.0. Ngoku ngumgangatho kunye nesixhobo esiphambili sokusebenza nge-asynchrony. Nayiphi na ikhowudi esebenzisa indlela endala ithathwa njengelifa. Iyunithi esisiseko ye-TPL yiklasi yoMsebenzi esuka kwi-System.Threading.Tasks namespace. Umsebenzi sisithabazi phezu komsonto. Ngoguqulelo olutsha lolwimi lwe-C #, sifumene indlela entle yokusebenza kunye neMisebenzi - async/ait operators. Ezi ngcamango zenze ukuba kube lula ukubhala ikhowudi ye-asynchronous njengokuba ilula kwaye i-synchronous, oku kwenza ukuba kube lula nakubantu abanokuqonda okuncinci kokusebenza kwangaphakathi kweentambo ukuba babhale izicelo ezizisebenzisayo, izicelo ezingakhenkcezi xa zisenza imisebenzi emide. Ukusebenzisa i-async / ukulinda sisihloko senqaku elinye okanye aliqela, kodwa ndiza kuzama ukufumana umxholo wayo kwizivakalisi ezimbalwa:

  • I-async ngumlungisi wendlela yokubuyisela uMsebenzi okanye ukungabikho
  • kwaye ulinde ngumsebenzi ongathinteliyo wokulinda uMsebenzi.

Kwakhona: ulinde umqhubi, kwimeko jikelele (kukho okushiyekileyo), uya kukhulula intambo yangoku yophumezo ngakumbi, kwaye xa uMsebenzi ugqiba ukuphunyezwa kwawo, kunye nomsonto (enyanisweni, kuya kuba kuchanekile ngakumbi ukuthetha umxholo. , kodwa ngaphezulu koko kamva) izakuqhubeka isenza indlela phambili. Ngaphakathi .NET, lomatshini uphunyezwa ngendlela efanayo nembuyekezo yesivuno, xa indlela ebhaliweyo ijika ibeyiklasi yonke, engumatshini karhulumente kwaye inokuphunyezwa ngamaqhekeza ahlukeneyo ngokuxhomekeke kula mazwe. Nabani na onomdla angabhala nayiphi na ikhowudi elula esebenzisa i-asynс/await, aqokelele kwaye ajonge indibano esebenzisa iJetBrains dotPeek eneCompiler Generated Code inikwe amandla.

Makhe sijonge iinketho zokusungula kunye nokusebenzisa uMsebenzi. Kumzekelo wekhowudi engezantsi, senza umsebenzi omtsha ongenzi nto iluncedo (Umsonto.Lala(10000)), kodwa kubomi bokwenyani oku kufuneka kube ngumsebenzi onzima we-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
}

Umsebenzi wenziwe ngenani leenketho:

  • I-LongRunning isalathiso sokuba umsebenzi awuyi kugqitywa ngokukhawuleza, oku kuthetha ukuba kunokuba kufanelekile ukuqwalasela ukungathathi intambo echibini, kodwa ukudala owahlukileyo kulo Msebenzi ukuze ungonakalisi abanye.
  • I-AttachedToParent - Imisebenzi inokucwangciswa ngokoluhlu lwemigangatho. Ukuba olu khetho lusetyenzisiwe, ngoko uMsebenzi unokuba kwimeko apho ugqityiwe kwaye ulindele ukubulawa kwabantwana bawo.
  • I-PreferFairness - ithetha ukuba kungangcono ukwenza imiSebenzi ethunyelwe ukuphunyezwa kwangoko phambi kokuba ithunyelwe kamva. Kodwa esi sisincomo nje kwaye iziphumo aziqinisekiswanga.

Iparameter yesibini egqithiselwe kwindlela yiCancellationToken. Ukusingatha ngokuchanekileyo ukurhoxiswa komsebenzi emva kokuba uqalile, ikhowudi ephunyeziweyo kufuneka izaliswe ngokutshekishwa kobume beCancellationToken. Ukuba akukho zitshekisho, ngoko indlela yokuRhoxisa ebizwa kwi-CancellationTokenSource into iya kuba nako ukumisa ukuphunyezwa koMsebenzi kuphela phambi kokuba uqale.

Iparamitha yokugqibela yinto yomcwangcisi wodidi lomSebenzi woMsebenzi. Olu didi kunye nenzala yalo ziyilelwe ukulawula izicwangciso zokusasaza imiSebenzi kwimisonto yonke, ngokungagqibekanga, uMsebenzi uza kuphunyezwa kumsonto ongacwangciswanga ukusuka echibini.

Umqhubi wokulinda usetyenziswe kuMsebenzi owenziweyo, oku kuthetha ukuba ikhowudi ebhaliweyo emva kwayo, ukuba kukho enye, iya kuphunyezwa kumxholo ofanayo (ngokuqhelekileyo oku kuthetha kwintambo efanayo) njengekhowudi ngaphambi kokulinda.

Indlela iphawulwe njenge-async void, oku kuthetha ukuba inokusebenzisa umqhubi wokulinda, kodwa ikhowudi yokufowuna ayiyi kukwazi ukulinda ukuphunyezwa. Ukuba uphawu olunjalo luyimfuneko, ngoko indlela kufuneka ibuyisele uMsebenzi. Iindlela eziphawulwe ukuba i-async yokungabikho zixhaphake kakhulu: njengomthetho, aba ngabaphathi bemisitho okanye ezinye iindlela ezisebenza emlilweni kwaye zilibale umgaqo. Ukuba awufuni ukunika kuphela ithuba lokulinda de kube sekupheleni kokubulawa, kodwa uphinde ubuyisele umphumo, ngoko kufuneka usebenzise uMsebenzi.

KuMsebenzi obuyiselweyo indlela ye-StartNew, kunye nakweyiphi na enye, ungafowunela i-ConfigureAwait indlela ngeparameter yobuxoki, emva koko uphumezo emva kokulinda luzakuqhubeka hayi kumxholo othinjiweyo, kodwa ngokungenasizathu. Oku kufuneka kuhlale kusenziwa xa umxholo wophumezo ungabalulekanga kwikhowudi emva kokulinda. Oku kwakhona kuyingcebiso evela kuMS xa kubhalwa ikhowudi eya kusiwa ipakishwe elayibrari.

Makhe sijonge ngakumbi malunga nendlela onokulinda ngayo ukugqitywa koMsebenzi. Apha ngezantsi kukho umzekelo wekhowudi, kunye nezimvo malunga nokuba ulindelo lwenziwa ngokufanelekileyo ngokwemeko kwaye xa lwenziwa ngokungalunganga ngokwemeko.

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
}

Kumzekelo wokuqala, silindele uMsebenzi ukuba ugqitywe ngaphandle kokuvala intambo yokufowuna; siya kubuyela ekuqhubeni isiphumo kuphela xa sele sikhona; kude kube ngoko, intambo yokufowuna ishiywe kwizixhobo zayo.

Kwinketho yesibini, sivimba intambo yokufowuna kude kube nesiphumo sendlela sibalwa. Oku kubi kungekuphela nje ngenxa yokuba siye sahlala intambo, isixhobo esixabisekileyo senkqubo, kunye nokungenzi nto okulula, kodwa nangenxa yokuba ikhowudi yendlela esiyibizayo iqulethe ukulinda, kwaye umxholo wongqamaniso ufuna ukubuyela kwintambo yokufowuna emva kokuba linda, emva koko siya kufumana i-deadlock : Umsonto wokufowuna ulinda isiphumo sendlela ye-asynchronous ukuba ibalwe, indlela ye-asynchronous izama ngelize ukuqhubeka nokwenziwa kwayo kumsonto wokufowuna.

Enye into engalunganga yale ndlela kukuphatha iimpazamo ezintsonkothileyo. Inyani kukuba iimpazamo kwikhowudi ye-asynchronous xa usebenzisa i-async / ukulinda kulula kakhulu ukusingatha - ziziphatha ngendlela efanayo ukuba ikhowudi i-synchronous. Ngelixa ukuba sisebenzisa i-synchronous wait exorcism kwi-Task, i-exception yasekuqaleni ijika ibe yi-AggregateException, okt. Ukuphatha ngaphandle, kuya kufuneka ujonge uhlobo lwe-InnerException kwaye ubhale ikhonkco ngokwakho ngaphakathi kwebhloko enye yokubambisa okanye usebenzise ukubamba xa usakha, endaweni yekhonkco leebhloko zokubamba eziqhelekileyo kwihlabathi le-C #.

Umzekelo wesithathu nowokugqibela nawo uphawulwe kakubi ngesizathu esifanayo kwaye uqulethe zonke iingxaki ezifanayo.

I- WhenAny and WhenAll iindlela zilungele kakhulu ukulinda iqela leMisebenzi; basonga iqela leMisebenzi kwenye, eliya kuthi livuthe nokuba xa uMsebenzi weqela uqala ukwenziwa, okanye xa bonke begqibile ukwenza.

Ukumisa imisonto

Ngenxa yezizathu ezahlukeneyo, kunokuba yimfuneko ukumisa ukuhamba emva kokuba kuqalisiwe. Kukho iindlela ezininzi zokwenza oku. Iklasi ye-Tread ineendlela ezimbini ezibizwa ngokufanelekileyo: Khupha isisu и Ukuphazamiseka. Eyokuqala ayikhuthazwa kakhulu ukuba isetyenziswe, kuba emva kokuyibiza nangawuphi na umzuzu ongaqhelekanga, ngexesha lokuqhutywa kwawo nawuphi na umyalelo, ngaphandle kuya kuphoswa ThreadAbortedException. Awulindelanga ukuba kuphoswe umkhethe onjalo xa unyuswa nakuphi na ukuguquguquka okupheleleyo, akunjalo? Kwaye xa usebenzisa le ndlela, le yimeko yokwenyani. Ukuba ufuna ukuthintela i-CLR ekuveliseni okungafaniyo kwicandelo elithile lekhowudi, ungayisonga ngeefowuni. Thread.BeginCriticalRegion, Umsonto.EndCriticalRegion. Nayiphi na ikhowudi ebhalwe kwibhloko ekugqibeleni isongelwe kwiifowuni ezinjalo. Ngesi sizathu, kubunzulu bekhowudi yesakhelo ungafumana iibhloko ngetry engenanto, kodwa hayi engenanto ekugqibeleni. UMicrosoft uyayityhafisa le ndlela kangangokuba zange ayifake kwi-.net core.

Indlela yokuphazamisa isebenza ngokuqikelelwa ngakumbi. Inokuphazamisa intambo ngaphandle kokukhetha ThreadInterruptedException kuphela ngaloo maxesha xa umsonto ukwimo yokulinda. Ingena kule meko ngelixa ijingayo ngelixa ilinde i-WaitHandle, itshixe, okanye emva kokufowunela i-Thread.Sleep.

Zombini iinketho ezichazwe ngasentla zimbi ngenxa yokungaqiniseki kwazo. Isisombululo kukusebenzisa isakhiwo CancellationToken kunye neklasi CancellationTokenSource. Ingongoma yile: umzekelo weklasi yeCancellationTokenSource yenziwe kwaye ngumniniyo kuphela onokumisa umsebenzi ngokubiza indlela. Rhoxisa. Kuphela luphawu lokurhoxisa olugqithiselwayo kumsebenzi ngokwawo. Abanini beCancellationToken abanakulurhoxisa umsebenzi ngokwabo, kodwa banokujonga kuphela ukuba umsebenzi urhoxisiwe. Kukho ipropathi yeBoolean kule nto Ukurhoxiswa kuceliwe kunye nendlela ThrowIfCancelRequested. Le yokugqibela iya kuphosa ngaphandle UmsebenziCancelledException ukuba indlela yokurhoxisa ibizwe kumzekelo wokuCallationToken ukuba i-parroted. Kwaye le yindlela endiyincomayo ukuyisebenzisa. Olu luphuculo ngaphezu kokhetho lwangaphambili ngokufumana ulawulo olupheleleyo malunga nokuba yeyiphi inqanaba umsebenzi ongeyomfuneko unokuyekiswa.

Olona khetho lukhohlakeleyo lokumisa intambo kukufowunela iWin32 API TerminateThread function. Ukuziphatha kwe-CLR emva kokubiza lo msebenzi kunokungacingelwanga. Kwi-MSDN kubhalwe oku kulandelayo malunga nalo msebenzi: “I-TerminateThread ngumsebenzi onobungozi ekufuneka usetyenziswe kuphela kwezona meko zinzima. “

Ukuguqula i-API yelifa ukuya kwi-Task Based usebenzisa indlela esuka kwi-Async

Ukuba unethamsanqa ngokwaneleyo lokusebenza kwiprojekthi eyaqalwa emva kokuziswa kweMisebenzi kwaye yayeka ukubangela ukoyikeka okuthe cwaka kuninzi lwabaphuhlisi, ke awuzukujongana nee-APIs ezindala, zombini ezomntu wesithathu kunye neqela lakho. uye wangcungcuthekisa kwixesha elidlulileyo. Ngethamsanqa, iqela le-NET Framework lasinyamekela, nangona mhlawumbi injongo yayikukuzinyamekela. Kungakhathaliseki ukuba kunjalo, i-NET inenani lezixhobo zokuguqula ngokungenabuhlungu ikhowudi ebhalwe kwiindlela zakudala zenkqubo ye-asynchronous ukuya kwentsha. Enye yazo yindlela esuka kuAsync yeTaskFactory. Kumzekelo wekhowudi engezantsi, ndisongela iindlela zakudala ze-async zeklasi yeWebRequest kwi-Task usebenzisa le ndlela.

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

Lo ngumzekelo nje kwaye akunakufane kwenzeke ukuba wenze oku ngeendidi ezakhelwe ngaphakathi, kodwa nayiphi na iprojekthi endala izele ziindlela ze-BeginDoSomething ezibuyisela i-IAsyncResult kunye ne-EndDoSomething iindlela eziyifumanayo.

Guqula i-API yelifa ukuya kwi-Task Based usebenzisa iklasi ye-TaskCompletionSource

Esinye isixhobo esibalulekileyo ekufuneka siqwalaselwe yiklasi TaskCompletionSource. Ngokubhekiselele kwimisebenzi, injongo kunye nomgaqo wokusebenza, kunokukhumbuza indlela ye-RegisterWaitForSingleObject yeklasi ye-ThreadPool, endibhale ngayo ngasentla. Usebenzisa le klasi, unokusonga ngokulula nangokulungeleyo ii-API ezindala ze-asynchronous kwiMisebenzi.

Uya kuthi sele ndithethile malunga nendlela yokusuka kwi-Async yeklasi ye-TaskFactory eyenzelwe ezi njongo. Apha kuya kufuneka sikhumbule yonke imbali yokuphuhliswa kweemodeli ze-asynchronous kwi-.net ukuba iMicrosoft inikeze kwiminyaka eyi-15 edluleyo: ngaphambi koMsebenzi oSekwe kwi-Asynchronous Pattern (TAP), bekukho i-Asynchronous Programming Pattern (APP), leyo. yayimalunga neendlela QalaYenza into ebuyayo IAsyncResult kunye neendlela IsipheloDoSomething eyamkelayo kunye nelifa lale minyaka indlela esuka kuAsync igqibelele, kodwa ekuhambeni kwexesha, yathatyathelwa indawo yiSigigaba esekwe kwiAsynchronous Pattern (KUNYE AP), ecingela ukuba isiganeko siya kuphakanyiswa xa umsebenzi we-asynchronous ugqityiwe.

I-TaskCompletionSource ilungile ekusongelweni kweMisebenzi kunye ne-APIs yelifa eyakhiwe malunga nemodeli yomsitho. Ingundoqo yomsebenzi wayo ngolu hlobo lulandelayo: into yale klasi inepropati yoluntu yohlobo lwe-Task, imeko enokuthi ilawulwe nge-SetResult, i-SetException, njl. iindlela ze-TaskCompletionSource iklasi. Kwiindawo apho ulindelo lusetyenziswe kulo Msebenzi, uya kuphunyezwa okanye ungaphumeleli ngaphandle kokuxhomekeka kwindlela esetyenziswayo kwi-TaskCompletionSource. Ukuba ayikacaci, makhe sijonge lo mzekelo wekhowudi, apho enye i-EAP API endala isongelwe kwi-Task usebenzisa i-TaskCompletionSource: xa isiganeko sivutha, uMsebenzi uya kudluliselwa kwisimo esiGqibileyo, kunye nendlela esetyenziswe ngumqhubi wokulinda. kulo Msebenzi izakuphinda iqalise ukuphunyezwa kwayo emva kokufumana into siphumo.

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

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

    result completionSource.Task;
}

Iingcebiso zoMsebenzi wokuQeda kunye namaqhinga

Ukusonga ii-APIs ezindala ayisiyiyo yonke into enokwenziwa kusetyenziswa i-TaskCompletionSource. Ukusebenzisa le klasi kuvula ithuba elinomdla lokuyila ii-APIs ezahlukeneyo kwiMisebenzi engathathi imisonto. Kwaye umlambo, njengoko sikhumbula, ngumthombo obiza kakhulu kwaye inani labo lilinganiselwe (ikakhulukazi ngesixa se-RAM). Lo mda unokufezekiswa ngokulula ngokuphuhlisa, umzekelo, usetyenziso lwewebhu olulayishiweyo olunengqiqo yoshishino oluntsonkothileyo. Makhe siqwalasele amathuba endithetha ngawo xa kuphunyezwa iqhinga elinje ngoLong-olude.

Ngamafutshane, ingundoqo yeqhinga yile: kufuneka ufumane ulwazi kwi-API malunga neziganeko ezithile ezenzeka kwicala layo, ngelixa i-API, ngenxa yesizathu esithile, ayikwazi ukubika umcimbi, kodwa inokubuyisela kuphela urhulumente. Umzekelo wazo zonke ii-API ezakhiwe phezulu kwe-HTTP ngaphambi kwexesha leWebSocket okanye xa kwakungenakwenzeka ngesizathu esithile sokusebenzisa le teknoloji. Umxhasi unokubuza umncedisi we HTTP. Umncedisi we HTTP akanako ukuqalisa unxibelelwano nomxhasi. Isisombululo esilula kukuvota umncedisi usebenzisa i-timer, kodwa oku kudala umthwalo owongezelelweyo kumncedisi kunye nokulibaziseka okongeziweyo kumyinge we-TimerInterval / 2. Ukujikeleza oku, iqhinga elibizwa ngokuba yi-Long Polling yasungulwa, ebandakanya ukulibazisa impendulo evela. umncedisi kude kuphele ixesha okanye isiganeko siyakwenzeka. Ukuba isiganeko senzeke, ngoko siqhutywe, ukuba akunjalo, ngoko isicelo sithunyelwa kwakhona.

while(!eventOccures && !timeoutExceeded)  {

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

Kodwa isisombululo esinjalo siya kubonakala sisoyikeka ngokukhawuleza ukuba inani labathengi abalinde umsitho landa, kuba ... Umxhasi ngamnye uthatha intambo epheleleyo elindele umsitho. Ewe, kwaye sifumana ukulibaziseka okongeziweyo kwe-1ms xa isiganeko sibangelwa, ngokuqhelekileyo oku akubalulekanga, kodwa kutheni ukwenza isofthiwe ibe yimbi ngakumbi kunokuba inokuba njalo? Ukuba sisusa i-Thread.Sleep (1), ngoko ngelize siya kulayisha enye i-processor core 100% engenzi lutho, ejikelezayo kumjikelezo ongenamsebenzi. Usebenzisa i-TaskCompletionSource unokwenza ngokulula kwakhona le khowudi kwaye usombulule zonke iingxaki ezichongiweyo ngasentla:

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

Le khowudi ayilungele imveliso, kodwa idemo nje. Ukuyisebenzisa kwiimeko zangempela, kufuneka kwakhona, ubuncinci, ukusingatha imeko xa umyalezo ufika ngexesha apho kungekho mntu ulindeleyo: kulo mzekelo, indlela ye-AsseptMessageAsync kufuneka ibuyisele uMsebenzi osele ugqityiwe. Ukuba le yeyona meko ixhaphakileyo, ngoko unokucinga ngokusebenzisa iValueTask.

Xa sifumana isicelo somyalezo, senza kwaye sibeke i-TaskCompletionSource kwisichazi-magama, kwaye emva koko silindele okwenzekayo kuqala: ixesha lekhefu elichaziweyo liphelelwa okanye umyalezo ufunyenwe.

ValueTask: kutheni kwaye njani

Abaqhubi be-async / balinde, njengomqhubi wokubuyisela isivuno, bavelise umatshini wombuso ukusuka kwindlela, kwaye oku kukudala into entsha, ephantse ingabinanto ibalulekileyo, kodwa kwiimeko ezinqabileyo kunokudala ingxaki. Le meko inokuba yindlela ebizwa ngokuba rhoqo rhoqo, sithetha ngamashumi kunye namakhulu amawaka eefowuni ngomzuzwana. Ukuba indlela enjalo ibhalwe ngendlela yokuba kwiimeko ezininzi ibuyisela isiphumo ngokudlula zonke iindlela zokulinda, ngoko .NET ibonelela ngesixhobo sokwandisa oku - iValueTask isakhiwo. Ukuyenza icace, makhe sijonge umzekelo wokusetyenziswa kwayo: kukho i-cache esiya kuyo rhoqo. Kukho amaxabiso kuyo kwaye emva koko sizibuyisele ngokulula; ukuba akunjalo, emva koko siya kwi-IO ecothayo ukuze siyifumane. Ndifuna ukwenza okokugqibela ngokulandelelana, okuthetha ukuba yonke indlela ijika ibeyi-asynchronous. Ke, indlela ecacileyo yokubhala indlela yile ilandelayo:

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

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

Ngenxa yomnqweno wokwandisa kancinci, kunye noloyiko oluncinci lwento eyakwenziwa nguRoslyn xa equlunqa le khowudi, ungaphinda uwubhale lo mzekelo ngolu hlobo lulandelayo:

public Task<string> GetById(int id) {

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

Ngokwenene, esona sisombululo sisiso kule meko inokuba kukwandisa indlela eshushu, oko kukuthi, ukufumana ixabiso kwisichazi-magama ngaphandle kolwabiwo olungeyomfuneko kunye nomthwalo kwi-GC, ngelixa kwezo meko zinqabileyo xa sisafuna ukuya kwi-IO ukufumana idatha. , yonke into iya kuhlala idibanisa / thabatha indlela yakudala:

public ValueTask<string> GetById(int id) {

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

Makhe sihlolisise le ngcezu yekhowudi: ukuba kukho ixabiso kwi-cache, sakha isakhiwo, ngaphandle koko umsebenzi wangempela uya kufakwa kwintsingiselo. Ikhowudi yokufowuna ayikhathali ukuba yeyiphi na indlela le khowudi esetyenziswe kwi: ValueTask, ukusuka kwindawo yemboniselo ye-C # yesintaksi, izakuziphatha ngendlela enye njengoMsebenzi oqhelekileyo kulo mzekelo.

I-TaskSchedulers: ukulawula izicwangciso zokuqaliswa komsebenzi

I-API elandelayo endifuna ukuyiqwalasela yiklasi Umcwangcisi woMsebenzi kunye nezinto eziphuma kuyo. Sele ndikhankanyile ngasentla ukuba i-TPL inamandla okulawula izicwangciso zokusasaza iMisebenzi kwimisonto yonke. Ezo zicwangciso zichazwe kwinzala yodidi lwe-TaskScheduler. Phantse nasiphi na isicwangciso onokuthi usifune sinokufumaneka kwithala leencwadi. ParallelExtensionsExtras, iphuhliswe nguMicrosoft, kodwa ingeyonxalenye ye.NET, kodwa inikezelwe njengepakethe yeNuget. Makhe sijonge ngokufutshane ezinye zazo:

  • CurrentThreadTaskScheduler — yenza ImiSebenzi kumsonto wangoku
  • LimitedConcurrencyLevelTaskScheduler — unciphisa inani leMisebenzi eyenziwe ngaxeshanye ngeparameter N, eyamkelwe kumakhi
  • I-OrderedTaskScheduler — ichazwa njenge LimitedConcurrencyLevelTaskScheduler(1), ngoko ke imisebenzi iya kwenziwa ngokulandelelanayo.
  • WorkStealingTaskScheduler - izixhobo umsebenzi-ubusela indlela yokusasazwa komsebenzi. Ngokusisiseko yi-ThreadPool eyahlukileyo. Isombulula ingxaki kwi-.NET ThreadPool yiklasi engatshintshiyo, enye yazo zonke izicelo, okuthetha ukuba ukulayisha ngaphezulu okanye ukusetyenziswa okungachanekanga kwindawo enye yenkqubo kunokukhokelela kwiziphumo ebezingalindelekanga kwenye. Ngaphezu koko, kunzima kakhulu ukuqonda unobangela wezi ziphene. Oko. Kusenokubakho imfuneko yokusebenzisa ii-WorkStealingTaskSchedules ezahlukeneyo kwiindawo zeprogram apho ukusetyenziswa kwe-ThreadPool kunokuba ndlongondlongo kwaye kungalindelekanga.
  • IQueuedTaskScheduler — ikuvumela ukuba wenze imisebenzi ngokwemigaqo ephambili yoluhlu
  • I-ThreadPerTaskScheduler — yenza umsonto owahlukileyo kuMsebenzi ngamnye owenziwe kuwo. Inokuba luncedo kwimisebenzi ethatha ixesha elide ngokungalindelekanga ukuyigqiba.

Kukho iinkcukacha ezintle inqaku malunga neTaskSchedulers kwiblogi yeMicrosoft.

Ukulungisa kakuhle yonke into enxulumene neMisebenzi, iVisual Studio inefestile yeMisebenzi. Kule festile ungabona imeko yangoku yomsebenzi kwaye utsibe kumgca ophunyezwayo wekhowudi yangoku.

.NET: Izixhobo zokusebenza nge-multithreading kunye ne-asynchrony. Icandelo loku-1

I-PLinq kunye neklasi yeParallel

Ukongeza kwiMisebenzi kunye nayo yonke into ethethiweyo ngayo, kukho izixhobo ezibini ezinomdla ngakumbi kwi-NET: I-PLinq (Linq2Parallel) kunye neklasi yeParallel. Eyokuqala ithembisa ukuphunyezwa okufanayo kwayo yonke imisebenzi ye-Linq kwimisonto emininzi. Inani lemisonto lingaqwalaselwa kusetyenziswa indlela yolwandiso lwe WithDegreeOfParallelism. Ngelishwa, amaxesha amaninzi i-PLinq kwimowudi yayo engagqibekanga ayinalo ulwazi olwaneleyo malunga nabangaphakathi bomthombo wakho wedatha ukubonelela ngenzuzo enkulu yesantya, kwelinye icala, ixabiso lokuzama liphantsi kakhulu: kufuneka nje ufowunele indlela ye-AsParallel ngaphambili. ikhonkco leendlela ze-Linq kunye nokuqhuba iimvavanyo zokusebenza. Ngaphaya koko, kuyenzeka ukuba ugqithise ulwazi olongezelelweyo kwi-PLinq malunga nobume bomthombo wakho wedatha usebenzisa indlela yoKwahlulahlula. Unokufunda ngakumbi apha и apha.

I-Parallel static class ibonelela ngeendlela zokuphinda-phinda ngengqokelela ye-Foreach ngokunxuseneyo, ukwenza i-Loop, kunye nokwenza abathunywa abaninzi kwi-Invoke efanayo. Ukuphunyezwa komsonto wangoku kuya kunqunyanyiswa de izibalo zigqitywe. Inani lemisonto lingaqwalaselwa ngokudlula iParallelOptions njengengxabano yokugqibela. Ungakhankanya kwakhona i-TaskScheduler kunye neCancellationToken usebenzisa iinketho.

ezifunyanisiweyo

Xa ndiqala ukubhala eli nqaku ngokusekelwe kwizixhobo zengxelo yam kunye nolwazi endiluqokelele ngexesha lomsebenzi wam emva kwayo, andizange ndilindele ukuba kuya kubakho okuninzi. Ngoku, xa umhleli wombhalo apho ndichwetheza khona eli nqaku ngokuthuka undixelela ukuba iphepha le-15 lihambile, ndiza kushwankathela iziphumo zethutyana. Amanye amaqhinga, ii-APIs, izixhobo ezibonakalayo kunye nemigibe ziya kubandakanywa kwinqaku elilandelayo.

Izigqibo:

  • Kuya kufuneka wazi izixhobo zokusebenza kunye neentambo, i-asynchrony kunye ne-parallelism ukuze usebenzise izixhobo zeePC zanamhlanje.
  • I-NET inezixhobo ezininzi ezahlukeneyo kwezi njongo
  • Ayizizo zonke zavela ngaxeshanye, ngoko unokufumana rhoqo ilifa, nangona kunjalo, kukho iindlela zokuguqula ii-API ezindala ngaphandle komgudu omkhulu.
  • Ukusebenza ngemisonto kwi.NET imelwe ziiklasi ze Thread and ThreadPool
  • I-Thread.Abort, Thread.Interrupt, kunye Win32 API TerminateThread iindlela ziyingozi kwaye azikhuthazwa ukuba zisetyenziswe. Endaweni yoko, kungcono ukusebenzisa indlela yeCancellationToken
  • Ukuhamba sisixhobo esixabisekileyo kwaye unikezelo lwayo lulinganiselwe. Iimeko apho imisonto ixakekile ilindele iziganeko kufuneka ziphetshwe. Kule nto kulungele ukusebenzisa iklasi ye-TaskCompletionSource
  • Ezona zixhobo zinamandla neziqhubela phambili zeNET zokusebenza kunye neparallelism kunye ne-asynchrony yiMisebenzi.
  • I-c# async/await abaqhubi baphumeza ingqikelelo yokungathinteli ukulinda
  • Ungalawula unikezelo lweMisebenzi kwimisonto yonke usebenzisa iiklasi eziphuma kwi-TaskScheduler
  • Ubume beValueTask bunokuba luncedo ekwandiseni iindlela ezishushu kunye nememori-traffic
  • ImiSebenzi yeSitudiyo esiBonakalayo kunye neMisonto windows ibonelela ngolwazi oluninzi oluluncedo ukulungisa imisonto emininzi okanye ikhowudi engatshintshiyo.
  • I-PLinq sisixhobo esipholileyo, kodwa isenokungabi nolwazi olwaneleyo malunga nomthombo wakho wedatha, kodwa oku kunokulungiswa kusetyenziswa indlela yokwahlulahlula.
  • Iza kuqhubeka…

umthombo: www.habr.com

Yongeza izimvo