.NET: Cov cuab yeej rau kev ua hauj lwm nrog multithreading thiab asynchrony. Ntu 1

Kuv tabtom tshaj tawm thawj tsab xov xwm ntawm Habr, cov lus txhais uas tau muab tso rau hauv lub tuam txhab blog xa.

Qhov yuav tsum tau ua ib yam dab tsi asynchronously, tsis tau tos rau qhov tshwm sim ntawm no thiab tam sim no, los yog faib cov hauj lwm loj ntawm ob peb chav ua nws, muaj ua ntej lub sij hawm ntawm lub computer. Nrog lawv qhov kev tshwm sim, qhov kev xav tau no tau dhau los ua qhov tseeb. Tam sim no, xyoo 2019, Kuv tab tom ntaus cov kab lus no ntawm lub laptop nrog 8-core Intel Core processor, uas ntau tshaj li ib puas cov txheej txheem tau khiav hauv qhov sib npaug, thiab ntau cov xov. Nyob ze, muaj lub xov tooj me me, yuav ob peb xyoos dhau los, nws muaj 8-core processor ntawm lub nkoj. Cov peev txheej thematic yog tag nrho ntawm cov ntawv thiab cov yeeb yaj kiab uas lawv cov neeg sau qhuas qhuas xyoo no cov xov tooj zoo tshaj plaws uas muaj 16-core processors. MS Azure muab lub tshuab virtual nrog 20 core processor thiab 128 TB RAM tsawg dua $ 2 / teev. Hmoov tsis zoo, nws yog tsis yooj yim sua kom rho tawm qhov siab tshaj plaws thiab siv lub zog no yam tsis muaj peev xwm tswj hwm kev sib cuam tshuam ntawm cov xov.

Terminology

Txheej txheem - OS khoom, qhov chaw nyob cais, muaj cov xov.
Xov - ib qho khoom OS, qhov tsawg tshaj plaws ntawm kev tua, ib feem ntawm cov txheej txheem, xov sib koom nco thiab lwm yam kev pab ntawm lawv tus kheej hauv cov txheej txheem.
Multitasking - OS cov cuab yeej, muaj peev xwm khiav ntau cov txheej txheem ib txhij
Multi-core - cov cuab yeej ntawm lub processor, muaj peev xwm siv ntau lub cores rau kev ua cov ntaub ntawv
Multiprocessing - cov cuab yeej ntawm lub khoos phis tawj, muaj peev xwm ua haujlwm ib txhij nrog ntau lub processors lub cev
Multithreading - Cov cuab yeej ntawm cov txheej txheem, muaj peev xwm faib cov ntaub ntawv ua haujlwm ntawm ntau cov xov.
Parallelism - ua ntau yam kev ua ntawm lub cev ib txhij rau ib chav tsev ntawm lub sijhawm
Asynchrony - Kev ua tiav ntawm kev ua haujlwm yam tsis tau tos kom tiav ntawm qhov kev ua tiav no; cov txiaj ntsig ntawm kev ua tiav tuaj yeem ua tiav tom qab.

Kev ua piv txwv

Tsis yog txhua lub ntsiab lus yog qhov zoo thiab qee qhov xav tau kev piav qhia ntxiv, yog li kuv yuav ntxiv ib qho piv txwv txog kev noj tshais rau cov lus qhia raug cai. Ua noj tshais hauv qhov piv txwv no yog txheej txheem.

Thaum kuv npaj pluas tshais thaum sawv ntxov kuv (CPU) Kuv tuaj rau hauv chav ua noj (Khoos phib tawj). Kuv muaj 2 txhais tes (cores). Muaj ntau yam khoom siv hauv chav ua noj (IO): cub, kettle, toaster, tub yees. Kuv qhib lub roj, muab lub lauj kaub rau nws thiab ncuav roj rau hauv nws yam tsis tau tos kom nws sov (asynchronously, Tsis-Blocking-IO-Tos), Kuv tshem cov qe tawm ntawm lub tub yees thiab tawg rau hauv ib lub phaj, ces tuav lawv nrog ib txhais tes (Xov xwm #1), thiab thib ob (Xov xwm #2) tuav lub phaj (Sib koom Resource). Tam sim no kuv xav qhib lub hwj, tab sis kuv tsis muaj tes txaus (Xov Starvation) Thaum lub sij hawm no, lub lauj kaub frying heats li (Processing result) rau hauv uas kuv ncuav dab tsi kuv tau nplawm. Kuv ncav tes rau lub lauj kaub thiab tig nws thiab stupidly saib cov dej kub hauv nws (Thaiv-IO-Tos), txawm hais tias lub sijhawm no nws tuaj yeem ntxuav lub phaj uas nws nplawm lub omelet.

Kuv noj omelette siv 2 txhais tes xwb, thiab kuv tsis muaj ntau, tab sis tib lub sijhawm, thaum lub sijhawm nplawm lub omelette, 3 txoj haujlwm tau tshwm sim ib zaug: nplawm lub omelette, tuav lub phaj, cua sov lub lauj kaub. . CPU yog qhov ceev tshaj plaws ntawm lub khoos phis tawj, IO yog dab tsi feem ntau txhua yam qeeb qeeb, yog li feem ntau qhov kev daws teeb meem zoo yog los tuav CPU nrog qee yam thaum tau txais cov ntaub ntawv los ntawm IO.

Txuas ntxiv qhov piv txwv:

  • Yog hais tias nyob rau hauv tus txheej txheem ntawm kev npaj ib tug omelet, kuv kuj yuav sim hloov khaub ncaws, qhov no yuav yog ib qho piv txwv ntawm multitasking. Ib qho tseem ceeb nuance: khoos phis tawj zoo dua ntawm qhov no ntau dua li tib neeg.
  • Ib chav ua noj nrog ntau tus kws ua zaub mov, piv txwv li hauv tsev noj mov - ntau lub khoos phis tawj.
  • Ntau lub tsev noj mov hauv lub tsev hais plaub zaub mov hauv lub khw muag khoom - cov ntaub ntawv chaw

.NET Cov cuab yeej

.NET yog qhov zoo ntawm kev ua haujlwm nrog threads, zoo li nrog ntau lwm yam. Nrog rau txhua qhov tshiab, nws nthuav tawm ntau thiab ntau cov cuab yeej tshiab rau kev ua haujlwm nrog lawv, cov txheej txheem tshiab ntawm kev xav dhau OS xov. Thaum ua hauj lwm nrog kev tsim kho ntawm abstractions, lub moj khaum developers siv ib tug mus kom ze uas tso lub cib fim, thaum siv ib tug high-theem abstraction, mus down ib los yog ntau theem hauv qab no. Feem ntau qhov no tsis tsim nyog, qhov tseeb nws qhib lub qhov rooj rau tua koj tus kheej hauv ko taw nrog rab phom phom, tab sis qee zaum, tsis tshua muaj, nws yuav yog tib txoj hauv kev los daws qhov teeb meem uas tsis tau daws nyob rau theem tam sim no ntawm abstraction. .

Los ntawm cov cuab yeej, kuv txhais tau hais tias ob qho tib si daim ntawv thov programming interfaces (APIs) muab los ntawm lub moj khaum thiab cov pob khoom thib peb, nrog rau tag nrho cov kev daws teeb meem software uas yooj yim rau kev tshawb nrhiav cov teeb meem cuam tshuam nrog ntau txoj xov tooj.

Pib ib txoj xov

Thread class yog chav kawm yooj yim tshaj plaws hauv .NET rau kev ua haujlwm nrog threads. Tus neeg tsim khoom lees txais ib qho ntawm ob tus neeg sawv cev:

  • ThreadStart - Tsis muaj qhov ntsuas
  • ParameterizedThreadStart - nrog ib qho parameter ntawm hom khoom.

Tus delegate yuav raug tua nyob rau hauv cov xov tshiab tsim tom qab hu rau txoj kev pib.Yog hais tias ib tug delegate ntawm hom ParametrizedThreadStart tau dhau mus rau tus tsim, ces ib yam khoom yuav tsum tau dhau mus rau txoj kev pib. Cov txheej txheem no yog xav tau los hloov cov ntaub ntawv hauv zos rau cov kwj deg. Nws yog ib qho tsim nyog sau cia tias tsim cov xov yog kev ua haujlwm kim, thiab xov nws tus kheej yog ib qho khoom hnyav, yam tsawg kawg vim nws faib 1MB ntawm lub cim xeeb ntawm pawg thiab yuav tsum muaj kev cuam tshuam nrog OS API.

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

ThreadPool chav kawm sawv cev rau lub tswv yim ntawm lub pas dej. Hauv .NET, xov pas dej yog ib qho ntawm engineering, thiab cov neeg tsim khoom ntawm Microsoft tau siv zog ntau los ua kom nws ua haujlwm tau zoo hauv ntau qhov xwm txheej.

General tswvyim:

Txij li thaum daim ntawv thov pib, nws tsim ob peb threads nyob rau hauv cia nyob rau hauv keeb kwm yav dhau thiab muab lub peev xwm coj lawv mus siv. Yog tias threads siv ntau zaus thiab ntau, lub pas dej ua ke nthuav dav kom tau raws li tus neeg hu xov tooj xav tau. Thaum tsis muaj cov xov dawb hauv lub pas dej ua ke thaum lub sijhawm, nws yuav tos rau ib qho ntawm cov xov rov qab, lossis tsim ib qho tshiab. Nws ua raws li cov xov pas dej ua ke yog qhov zoo rau qee qhov kev ua haujlwm luv luv thiab tsis zoo rau kev ua haujlwm uas khiav raws li kev pabcuam thoob plaws tag nrho cov haujlwm ntawm daim ntawv thov.

Txhawm rau siv cov xov los ntawm lub pas dej, muaj QueueUserWorkItem txoj kev uas lees txais ib tus neeg sawv cev ntawm hom WaitCallback, uas muaj tib lub npe kos npe raws li ParametrizedThreadStart, thiab qhov ntsuas tau dhau mus rau nws ua haujlwm tib yam.

ThreadPool.QueueUserWorkItem(...);

Txoj kev tsis tshua paub cov xov pas dej ua ke RegisterWaitForSingleObject yog siv los npaj cov haujlwm tsis thaiv IO. Tus neeg sawv cev dhau mus rau txoj kev no yuav raug hu thaum WaitHandle dhau mus rau txoj kev yog "Tshaj tawm".

ThreadPool.RegisterWaitForSingleObject(...)

.NET muaj xov timer thiab nws txawv ntawm WinForms/WPF timers nyob rau hauv uas nws handler yuav raug hu rau ntawm ib tug xov coj los ntawm lub pas dej ua ke.

System.Threading.Timer

Kuj tseem muaj txoj hauv kev zoo tshaj plaws los xa ib tus neeg sawv cev rau kev tua rau cov xov los ntawm lub pas dej - txoj kev BeginInvoke.

DelegateInstance.BeginInvoke

Kuv xav luv luv nyob ntawm qhov ua haujlwm uas muaj ntau txoj hauv kev saum toj no tuaj yeem hu ua - CreateThread los ntawm Kernel32.dll Win32 API. Muaj ib txoj hauv kev, ua tsaug rau cov txheej txheem ntawm cov txheej txheem sab nrauv, hu rau qhov haujlwm no. Kuv tau pom qhov kev hu no tsuas yog ib zaug hauv qhov piv txwv txaus ntshai ntawm txoj cai qub txeeg qub teg, thiab kev txhawb siab ntawm tus kws sau ntawv uas tau ua raws nraim qhov no tseem yog qhov tsis paub meej rau kuv.

Kernel32.dll CreateThread

Saib thiab Debugging Xov

Cov xov tsim los ntawm koj, tag nrho cov khoom thib peb, thiab .NET pas tuaj yeem pom hauv Threads qhov rai ntawm Visual Studio. Lub qhov rais no tsuas yog tso saib xov xov xwm thaum daim ntawv thov nyob rau hauv kev debug thiab hauv Break hom. Ntawm no koj tuaj yeem yooj yim saib cov npe pawg thiab qhov tseem ceeb ntawm txhua txoj xov, thiab hloov debugging mus rau ib qho xov. Siv cov cuab yeej tseem ceeb ntawm cov xov hauv chav kawm, koj tuaj yeem teeb tsa qhov tseem ceeb ntawm cov xov, uas OC thiab CLR yuav pom tau tias yog qhov kev pom zoo thaum faib cov sijhawm ua haujlwm ntawm cov xov.

.NET: Cov cuab yeej rau kev ua hauj lwm nrog multithreading thiab asynchrony. Ntu 1

Task Parallel Library

Task Parallel Library (TPL) tau qhia hauv .NET 4.0. Tam sim no nws yog tus qauv thiab cov cuab yeej tseem ceeb rau kev ua haujlwm nrog asynchrony. Txhua txoj cai uas siv txoj hauv kev qub yog suav tias yog keeb kwm yav dhau los. Chav tsev hauv paus ntawm TPL yog chav haujlwm ua haujlwm los ntawm System.Threading.Tasks namespace. Ib txoj haujlwm yog kev paub daws teeb meem ntawm cov xov. Nrog rau cov ntawv tshiab ntawm C# lus, peb tau txais txoj hauv kev zoo nkauj los ua haujlwm nrog Cov Haujlwm - async / tos tswv. Cov tswv yim no ua rau nws muaj peev xwm sau asynchronous code raws li nws yooj yim thiab synchronous, qhov no ua rau nws ua tau txawm tias cov neeg tsis tshua nkag siab txog kev ua haujlwm sab hauv ntawm cov xov los sau cov ntawv thov uas siv lawv, cov ntawv thov uas tsis khov thaum ua haujlwm ntev. Siv async / tos yog ib lub ntsiab lus rau ib lossis ob peb kab lus, tab sis kuv yuav sim kom tau txais cov ntsiab lus ntawm nws hauv ob peb kab lus:

  • async yog ib qho kev hloov kho ntawm ib txoj kev rov ua haujlwm lossis tsis muaj dab tsi
  • thiab tos yog tus neeg ua haujlwm uas tsis thaiv cov haujlwm tos.

Ib zaug ntxiv: tus neeg teb xov tooj tos, nyob rau hauv rooj plaub dav dav (muaj kev zam), yuav tso cov xov tam sim no ntawm kev ua tiav ntxiv, thiab thaum lub luag haujlwm tiav nws qhov kev ua tiav, thiab xov (qhov tseeb, nws yuav yog qhov tseeb dua los hais cov ntsiab lus. , tab sis ntxiv rau qhov ntawd tom qab) yuav txuas ntxiv ua txoj hauv kev ntxiv. Hauv .NET, qhov txheej txheem no yog siv tib txoj kev raws li cov txiaj ntsig rov qab, thaum cov txheej txheem sau tau hloov mus rau tag nrho cov chav kawm, uas yog lub xeev tshuab thiab tuaj yeem ua tiav hauv nyias daim nyob ntawm cov xeev no. Txhua tus neeg xav tau tuaj yeem sau cov lej yooj yim siv asynс / tos, sau thiab saib lub rooj sib txoos siv JetBrains dotPeek nrog Compiler Generated Code enabled.

Cia peb saib cov kev xaiv rau kev pib thiab siv Task. Hauv qhov piv txwv hauv qab no, peb tsim ib txoj haujlwm tshiab uas tsis muaj txiaj ntsig (Xov.Pw tsaug zog (10000)), tab sis nyob rau hauv lub neej tiag tiag no yuav tsum yog ib co complex CPU-intensive hauj lwm.

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
}

Ib Txoj Haujlwm yog tsim nrog ntau txoj kev xaiv:

  • LongRunning yog ib qho lus qhia tias txoj haujlwm yuav tsis ua tiav sai, uas txhais tau hais tias nws yuav tsim nyog xav tsis txhob siv xov los ntawm lub pas dej, tab sis tsim kom muaj ib qho cais rau Txoj Haujlwm no kom tsis txhob ua phem rau lwm tus.
  • AttachedToParent - Cov hauj lwm tuaj yeem teem caij rau hauv hierarchy. Yog tias qhov kev xaiv no tau siv, ces Txoj Haujlwm yuav nyob rau hauv lub xeev uas nws tus kheej tau ua tiav thiab tos rau kev tua nws cov menyuam.
  • PreferFairness - txhais tau tias nws yuav zoo dua los ua cov haujlwm xa mus rau kev ua tiav ua ntej cov xa tuaj tom qab. Tab sis qhov no tsuas yog kev pom zoo thiab cov txiaj ntsig tsis tau lees paub.

Qhov thib ob parameter dhau mus rau txoj kev yog CancellationToken. Txhawm rau kom raug tshem tawm ntawm kev ua haujlwm tom qab nws tau pib, tus lej raug tua yuav tsum tau sau nrog cov tshev rau lub xeev CancellationToken. Yog tias tsis muaj kev txheeb xyuas, ces txoj kev Ncua tseg hu ua CancellationTokenSource khoom yuav tuaj yeem nres qhov kev ua tiav ntawm Task nkaus xwb ua ntej nws pib.

Qhov kawg parameter yog lub sijhawm teem caij ntawm hom TaskScheduler. Cov chav kawm no thiab nws cov xeeb leej xeeb ntxwv tau tsim los tswj cov tswv yim rau kev faib cov haujlwm thoob plaws cov xov; los ntawm lub neej ntawd, Txoj Haujlwm yuav raug ua tiav ntawm cov xov tsis sib xws los ntawm lub pas dej.

Tus neeg teb xov tooj tos yog siv rau cov haujlwm tsim, uas txhais tau hais tias cov cai sau tom qab nws, yog tias muaj ib qho, yuav raug tua nyob rau hauv tib lub ntsiab lus (feem ntau qhov no txhais tau tias ntawm tib txoj xov) raws li cov cai ua ntej tos.

Cov txheej txheem yog cim async void, uas txhais tau hais tias nws tuaj yeem siv tus neeg teb xov tooj tos, tab sis tus lej hu yuav tsis tuaj yeem tos kom tiav. Yog tias qhov no yog qhov tsim nyog, ces txoj kev yuav tsum rov qab ua haujlwm. Cov txheej txheem cim async void yog qhov muaj ntau: raws li txoj cai, cov no yog cov neeg tuav kev tshwm sim lossis lwm txoj hauv kev uas ua haujlwm ntawm hluav taws thiab tsis nco qab lub hauv paus ntsiab lus. Yog tias koj xav tau tsis tsuas yog muab lub sijhawm tos kom txog thaum kawg ntawm kev ua tiav, tab sis kuj rov qab cov txiaj ntsig, ces koj yuav tsum siv Task.

Ntawm Txoj Haujlwm uas StartNew txoj kev rov qab los, nrog rau lwm yam, koj tuaj yeem hu rau ConfigureAwait txoj kev nrog rau qhov tsis muaj tseeb, tom qab ntawd kev ua tiav tom qab tos yuav txuas ntxiv tsis nyob rau hauv cov ntsiab lus raug ntes, tab sis ntawm qhov tsis txaus ntseeg. Qhov no yuav tsum ib txwm ua thaum cov ntsiab lus ua tiav tsis tseem ceeb rau cov cai tom qab tos. Qhov no kuj yog ib qho kev pom zoo los ntawm MS thaum sau cov lej uas yuav xa tuaj rau hauv lub tsev qiv ntawv.

Cia peb nyob me ntsis ntxiv txog yuav ua li cas koj tuaj yeem tos kom tiav ntawm Task. Hauv qab no yog ib qho piv txwv ntawm cov cai, nrog cov lus hais txog thaum qhov kev cia siab tau ua tiav zoo thiab thaum nws ua tiav tsis zoo.

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
}

Hauv thawj qhov piv txwv, peb tos kom ua tiav yam tsis tau thaiv cov xov xov tooj; peb yuav rov qab mus ua cov txiaj ntsig tsuas yog thaum nws twb muaj lawm; txog thaum ntawd, cov xov xov yuav raug tso rau nws tus kheej li.

Hauv qhov kev xaiv thib ob, peb thaiv cov xov tooj kom txog thaum cov txiaj ntsig ntawm txoj kev suav. Qhov no yog qhov phem tsis yog vim peb tau nyob hauv xov, xws li cov peev txheej tseem ceeb ntawm qhov kev pab cuam, nrog kev ua haujlwm yooj yim, tab sis kuj vim tias yog cov cai ntawm txoj kev uas peb hu muaj tos, thiab cov ntsiab lus synchronization yuav tsum rov qab mus rau xov tooj tom qab. tos, ces peb yuav tau txais ib tug deadlock: Xov xov tos rau qhov tshwm sim ntawm asynchronous txoj kev xam, asynchronous txoj kev sim nyob rau hauv vain mus txuas ntxiv nws tua nyob rau hauv lub hu xov.

Lwm qhov tsis zoo ntawm txoj hauv kev no yog kev ua yuam kev nyuaj. Qhov tseeb yog qhov yuam kev hauv asynchronous code thaum siv async / tos yog qhov yooj yim heev rau kev daws - lawv coj zoo ib yam li cov cai tau synchronous. Thaum yog tias peb siv synchronous tos exorcism rau Task, qhov kev zam qub dhau los ua AggregateException, i.e. Txhawm rau ua qhov kev zam, koj yuav tsum tau tshuaj xyuas hom InnerException thiab sau ib qho yog tias koj tus kheej hauv ib qho thaiv los yog siv tus ntes thaum tsim, es tsis txhob ntawm cov saw ntawm ntes blocks uas paub ntau dua hauv C# ntiaj teb.

Cov piv txwv thib peb thiab zaum kawg kuj tseem ceeb rau tib qho laj thawj thiab muaj tag nrho cov teeb meem tib yam.

Thaum twg thiab Thaum twg tag nrho cov txheej txheem yog qhov yooj yim heev rau tos rau ib pab pawg ua haujlwm; lawv qhwv ib pab pawg ua haujlwm rau hauv ib qho, uas yuav raug tua thaum ua haujlwm los ntawm pab pawg thawj zaug, lossis thaum tag nrho lawv tau ua tiav lawv qhov kev ua tiav.

Tso tseg cov xov

Rau ntau yam laj thawj, nws yuav tsum tau nres qhov ntws tom qab nws tau pib. Muaj ntau txoj hauv kev los ua qhov no. Chav Kawm Xov Xwm muaj ob txoj hauv kev uas tsim nyog: Nres и Kev cuam tshuam. Thawj tus yog heev tsis pom zoo rau siv, vim hais tias tom qab hu nws ntawm ib lub sijhawm random, thaum lub sijhawm ua cov lus qhia, qhov kev zam yuav raug pov tseg ThreadAbortedException. Koj tsis cia siab tias qhov kev zam no yuav raug muab pov tseg thaum nce ib tus lej sib txawv, txoj cai? Thiab thaum siv txoj kev no, qhov no yog qhov xwm txheej tiag tiag. Yog tias koj xav tau los tiv thaiv CLR los ntawm kev tsim qhov kev zam no hauv qee ntu ntawm cov lej, koj tuaj yeem qhwv nws hauv kev hu. Xov.BeginCriticalRegion, Xov.EndCriticalRegion. Txhua tus lej sau rau hauv qhov thaiv thaum kawg yog qhwv hauv cov kev hu no. Vim li no, nyob rau hauv qhov tob ntawm lub moj khaum code koj tuaj yeem pom cov blocks nrog kev sim khoob, tab sis tsis yog qhov khoob thaum kawg. Microsoft cuam tshuam txoj kev no ntau heev uas lawv tsis suav nrog hauv .net core.

Txoj kev cuam tshuam ua haujlwm tau zoo dua. Nws tuaj yeem cuam tshuam cov xov nrog kev zam ThreadInterruptedException tsuas yog thaum lub sijhawm ntawd thaum cov xov nyob hauv lub xeev tos. Nws nkag mus rau lub xeev no thaum dai thaum tos WaitHandle, xauv, lossis tom qab hu xov tooj.Sleep.

Ob qho kev xaiv tau piav qhia saum toj no yog qhov tsis zoo vim lawv qhov kev tsis pom zoo. Kev daws yog siv cov qauv CancellationToken thiab chav kawm CancellationTokenSource. Lub ntsiab lus yog qhov no: ib qho piv txwv ntawm cov chav kawm CancellationTokenSource yog tsim thiab tsuas yog tus tswv uas nws tuaj yeem txwv txoj haujlwm los ntawm kev hu rau txoj kev Ncua tseg. Tsuas yog CancellationToken tau dhau mus rau kev ua haujlwm nws tus kheej. Cov tswv CancellationToken tsis tuaj yeem tso tseg txoj haujlwm lawv tus kheej, tab sis tsuas yog tuaj yeem tshawb xyuas seb qhov haujlwm puas tau raug tshem tawm. Nws muaj Boolean cov cuab yeej rau qhov no IsCancellationRequested thiab txoj kev ThrowIfCancelRequested. Lub tom kawg yuav pov ib qho kev zam TaskCancelledException Yog hais tias txoj kev Ncua tseg tau hu rau ntawm CancellationToken piv txwv raug parroted. Thiab qhov no yog txoj kev kuv pom zoo siv. Qhov no yog ib qho kev txhim kho ntawm cov kev xaiv yav dhau los los ntawm kev tau txais kev tswj xyuas tag nrho ntawm qhov taw tes qhov kev zam tuaj yeem raug rho tawm.

Qhov kev xaiv phem tshaj plaws rau kev txwv txoj xov yog hu rau Win32 API TerminateThread muaj nuj nqi. Tus cwj pwm ntawm CLR tom qab hu rau qhov kev ua haujlwm no tej zaum yuav tsis paub txog. Ntawm MSDN cov lus hauv qab no tau sau txog qhov haujlwm no: "TerminateThread yog qhov ua haujlwm txaus ntshai uas yuav tsum tsuas yog siv rau qhov xwm txheej hnyav tshaj plaws. “

Hloov cov cuab yeej cuab tam API rau Task Based siv FromAsync txoj kev

Yog tias koj muaj hmoo txaus los ua haujlwm ntawm ib qhov project uas tau pib tom qab Kev Ua Haujlwm tau qhia thiab tso tseg ua rau muaj kev ntshai ntshai heev rau feem ntau cov neeg tsim khoom, ces koj yuav tsis tau cuam tshuam nrog ntau APIs qub, ob tog thib peb thiab cov neeg koj pab neeg. tau tsim txom yav dhau los. Hmoov zoo, pab pawg .NET Framework tau saib xyuas peb, txawm tias tej zaum lub hom phiaj yog saib xyuas peb tus kheej. Ua li ntawd, .NET muaj ib tug xov tooj ntawm cov cuab yeej rau painlessly converting code sau nyob rau hauv qub asynchronous programming mus kom ze rau tus tshiab. Ib tug ntawm lawv yog txoj kev FromAsync ntawm TaskFactory. Hauv qhov piv txwv hauv qab no, kuv qhwv cov txheej txheem async qub ntawm WebRequest chav kawm hauv Task siv txoj kev no.

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

Qhov no tsuas yog ib qho piv txwv thiab koj tsis zoo li yuav tsum tau ua qhov no nrog cov hom built-in, tab sis ib qho haujlwm qub tsuas yog teem caij nrog BeginDoSomething txoj kev uas rov qab IAsyncResult thiab EndDoSomething txoj kev uas tau txais nws.

Hloov cov cuab yeej cuab tam API rau Task Based siv TaskCompletionSource chav kawm

Lwm yam cuab yeej tseem ceeb uas yuav tau xav txog yog chav kawm TaskCompletionSource. Hais txog kev ua haujlwm, lub hom phiaj thiab lub hauv paus ntsiab lus ntawm kev ua haujlwm, nws yuav yog me ntsis nco txog RegisterWaitForSingleObject txoj kev ntawm ThreadPool chav kawm, uas kuv tau sau txog saum toj no. Siv cov chav kawm no, koj tuaj yeem yooj yim thiab yooj yim qhwv cov qub asynchronous APIs hauv Tasks.

Koj yuav hais tias kuv twb tau tham txog txoj kev FromAsync ntawm TaskFactory chav kawm npaj rau cov hom phiaj no. Ntawm no peb yuav tsum nco ntsoov tag nrho cov keeb kwm ntawm kev txhim kho asynchronous qauv hauv .net uas Microsoft tau muab rau 15 xyoo dhau los: ua ntej Task-Based Asynchronous Pattern (TAP), muaj Asynchronous Programming Pattern (APP), uas. yog hais txog txoj kev PibDoSomething rov qab IAsyncResult thiab txoj kev EndDoSomething uas lees txais nws thiab rau cov qub txeeg qub teg ntawm cov xyoo no txoj kev FromAsync tsuas yog zoo meej, tab sis dhau sij hawm, nws tau hloov los ntawm Cov Txheej Txheem Raws li Asynchronous Pattern (EAP), uas xav tias qhov xwm txheej yuav raug tsa thaum lub sijhawm ua haujlwm asynchronous tiav.

TaskCompletionSource yog qhov zoo tshaj plaws rau wrapping Tasks thiab legacy APIs tsim nyob ib ncig ntawm cov qauv kev tshwm sim. Lub ntsiab lus ntawm nws txoj haujlwm yog raws li hauv qab no: ib yam khoom ntawm chav kawm no muaj cov cuab yeej rau pej xeem ntawm hom Task, lub xeev uas tuaj yeem tswj tau los ntawm SetResult, SetException, thiab lwm yam txheej txheem ntawm chav kawm TaskCompletionSource. Hauv qhov chaw uas tus neeg teb xov tooj tos tau thov rau Txoj Haujlwm no, nws yuav raug tua lossis ua tsis tiav nrog kev zam nyob ntawm txoj kev siv rau TaskCompletionSource. Yog tias nws tseem tsis tau paub meej, cia peb saib cov piv txwv no code, qhov twg qee qhov qub EAP API tau qhwv hauv Task uas siv TaskCompletionSource: thaum qhov xwm txheej tshwm sim, Txoj Haujlwm yuav raug xa mus rau Lub Xeev Ua tiav, thiab cov txheej txheem uas siv tus neeg teb xov tooj tos. rau qhov haujlwm no yuav rov pib ua haujlwm tom qab tau txais qhov khoom tshwm sim.

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 Tips & Tricks

Wrapping qub APIs tsis yog txhua yam uas tuaj yeem ua tiav siv TaskCompletionSource. Siv cov chav kawm no qhib qhov muaj peev xwm nthuav dav ntawm kev tsim ntau yam APIs ntawm Cov Haujlwm uas tsis nyob hauv xov. Thiab cov kwj deg, raws li peb nco qab, yog ib qho khoom siv kim heev thiab lawv cov lej raug txwv (tsuas yog los ntawm tus nqi ntawm RAM). Qhov kev txwv no tuaj yeem ua tiav tau yooj yim los ntawm kev tsim, piv txwv li, ib daim ntawv thov lub vev xaib uas muaj kev lag luam nyuaj. Cia peb xav txog qhov muaj peev xwm uas kuv tab tom tham txog thaum siv qhov ua kom yuam kev xws li Long-Polling.

Hauv luv luv, lub ntsiab lus ntawm kev ua kom yuam kev yog qhov no: koj yuav tsum tau txais cov ntaub ntawv los ntawm API txog qee qhov xwm txheej tshwm sim ntawm nws sab, thaum API rau qee qhov laj thawj tsis tuaj yeem tshaj tawm qhov xwm txheej, tab sis tuaj yeem rov qab rau lub xeev. Ib qho piv txwv ntawm cov no yog tag nrho cov APIs ua rau saum HTTP ua ntej lub sijhawm ntawm WebSocket lossis thaum nws ua tsis tau rau qee qhov laj thawj los siv cov thev naus laus zis no. Tus neeg thov tuaj yeem nug HTTP server. HTTP server tsis tuaj yeem pib sib txuas lus nrog tus neeg siv khoom. Ib qho kev daws teeb meem yooj yim yog los soj ntsuam cov neeg rau zaub mov uas siv lub timer, tab sis qhov no tsim kev thauj khoom ntxiv ntawm tus neeg rau zaub mov thiab ncua sij hawm ntxiv ntawm qhov nruab nrab TimerInterval / 2. Kom tau txais ib ncig ntawm qhov no, ib qho kev ua kom yuam kev hu ua Long Polling tau tsim, uas cuam tshuam nrog kev ncua sij hawm los ntawm cov lus teb. neeg rau zaub mov kom txog thaum lub sij hawm tas sij hawm los yog ib qho kev tshwm sim yuav tshwm sim. Yog tias muaj xwm txheej tshwm sim, nws raug ua tiav; yog tias tsis yog, qhov kev thov raug xa rov qab.

while(!eventOccures && !timeoutExceeded)  {

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

Tab sis qhov kev daws teeb meem zoo li no yuav ua pov thawj txaus ntshai sai li sai tau thaum tus naj npawb ntawm cov neeg tau tos rau qhov tshwm sim nce, vim ... Txhua tus neeg siv khoom no muaj tag nrho cov xov xwm tos rau qhov xwm txheej. Yog lawm, thiab peb tau txais 1ms ncua ntxiv thaum qhov kev tshwm sim tshwm sim, feem ntau qhov no tsis tseem ceeb, tab sis vim li cas thiaj ua rau lub software phem dua li nws tuaj yeem ua tau? Yog tias peb tshem Thread.Sleep(1), ces nyob rau hauv vain peb yuav thauj ib processor core 100% idle, rotating nyob rau hauv ib tug tsis siv lub voj voog. Siv TaskCompletionSource koj tuaj yeem yooj yim remake cov cai no thiab daws txhua yam teeb meem uas tau teev tseg saum toj no:

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

Cov cai no tsis yog npaj txhij, tab sis tsuas yog demo xwb. Txhawm rau siv nws hauv cov xwm txheej tiag tiag, koj kuj xav tau, yam tsawg kawg, txhawm rau daws qhov xwm txheej thaum cov lus tuaj txog ntawm lub sijhawm uas tsis muaj leej twg xav txog: qhov no, AsseptMessageAsync txoj kev yuav tsum rov qab ua haujlwm tiav lawm. Yog tias qhov no yog qhov feem ntau, ces koj tuaj yeem xav txog kev siv ValueTask.

Thaum peb tau txais kev thov rau cov lus, peb tsim thiab tso TaskCompletionSource hauv phau ntawv txhais lus, thiab tom qab ntawd tos kom muaj dab tsi tshwm sim ua ntej: lub sijhawm teem caij nyoog dhau los lossis tau txais cov lus.

ValueTask: vim li cas thiab yuav ua li cas

Cov neeg ua haujlwm async / tos, zoo li tus neeg teb xov tooj xa rov qab, tsim lub xeev lub tshuab los ntawm txoj kev, thiab qhov no yog kev tsim cov khoom tshiab, uas yuav luag ib txwm tsis tseem ceeb, tab sis qee zaus nws tuaj yeem tsim teeb meem. Cov ntaub ntawv no tej zaum yuav yog ib txoj kev hu ua tiag tiag, peb tab tom tham txog kaum thiab pua pua txhiab tus hu ib ob. Yog hais tias xws li ib txoj kev yog sau nyob rau hauv xws li ib tug txoj kev uas nyob rau hauv feem ntau nws rov qab ib tug tshwm sim bypassing tag nrho cov tos txoj kev, ces .NET muab ib lub cuab tam los optimize qhov no - lub ValueTask qauv. Yuav kom paub meej, cia peb saib ib qho piv txwv ntawm nws siv: muaj ib lub cache uas peb mus rau ntau zaus. Muaj qee qhov tseem ceeb hauv nws thiab tom qab ntawd peb tsuas xa lawv rov qab; yog tias tsis yog, ces peb mus rau qee qhov qeeb IO kom tau txais lawv. Kuv xav ua qhov tom kawg asynchronously, uas txhais tau tias tag nrho cov txheej txheem hloov mus ua asynchronous. Yog li, txoj kev pom tseeb los sau cov qauv yog raws li hauv qab no:

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

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

Vim yog lub siab xav ua kom zoo me ntsis, thiab kev ntshai me ntsis ntawm Roslyn yuav tsim dab tsi thaum sau cov cai no, koj tuaj yeem sau cov piv txwv no raws li hauv qab no:

public Task<string> GetById(int id) {

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

Tseeb, qhov kev daws teeb meem zoo tshaj plaws hauv qhov no yuav yog txhawm rau txhim kho qhov kub-txoj kev, uas yog, tau txais tus nqi los ntawm phau ntawv txhais lus yam tsis muaj kev faib tsis tsim nyog thiab thauj khoom ntawm GC, thaum nyob rau hauv cov xwm txheej tsis tshua muaj thaum peb tseem xav tau mus rau IO rau cov ntaub ntawv. , txhua yam yuav nyob twj ywm ntxiv / rho tawm txoj kev qub:

public ValueTask<string> GetById(int id) {

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

Cia peb ua tib zoo saib ntawm cov cai no: yog tias muaj tus nqi hauv lub cache, peb tsim cov qauv, txwv tsis pub cov haujlwm tiag tiag yuav raug qhwv rau hauv ib qho tseem ceeb. Tus lej xov tooj tsis quav ntsej txog txoj hauv kev uas tus lej no tau ua tiav hauv: ValueTask, los ntawm C# syntax point of view, yuav coj tus cwj pwm zoo ib yam li Txoj Haujlwm tsis tu ncua hauv qhov no.

TaskSchedulers: tswj cov tswv yim pib ua haujlwm

API tom ntej uas kuv xav xav txog yog chav kawm TaskScheduler thiab nws cov derivatives. Kuv twb tau hais los saum toj no tias TPL muaj peev xwm los tswj cov tswv yim rau kev faib cov hauj lwm hla cov xov. Cov tswv yim zoo li no tau txhais hauv cov xeeb leej xeeb ntxwv ntawm TaskScheduler chav kawm. Yuav luag txhua lub tswv yim koj xav tau tuaj yeem pom hauv lub tsev qiv ntawv. ParallelExtensionsExtras, tsim los ntawm Microsoft, tab sis tsis yog ib feem ntawm .NET, tab sis muab raws li pob Nuget. Cia peb saib luv luv ntawm qee qhov ntawm lawv:

  • CurrentThreadTaskScheduler - executes Tasks ntawm cov xov tam sim no
  • LimitedConcurrencyLevelTaskScheduler - txwv tus naj npawb ntawm Cov Haujlwm ua tiav ib txhij los ntawm parameter N, uas tau txais hauv tus tsim
  • OrderedTaskScheduler - txhais tau tias yog LimitedConcurrencyLevelTaskScheduler(1), yog li cov dej num yuav raug ua tiav.
  • WorkStealingTaskScheduler - siv ua haujlwm nyiag mus kom ze rau kev faib ua haujlwm. Qhov tseem ceeb nws yog ThreadPool cais. daws qhov teeb meem uas hauv .NET ThreadPool yog chav kawm zoo li qub, ib qho rau txhua daim ntawv thov, uas txhais tau hais tias nws cov khoom siv ntau dhau los yog siv tsis raug hauv ib feem ntawm qhov kev pab cuam tuaj yeem ua rau muaj kev phiv rau lwm qhov. Ntxiv mus, nws yog qhov nyuaj heev kom nkag siab qhov ua rau ntawm qhov tsis xws luag. Qhov ntawd. Tej zaum yuav muaj qhov yuav tsum tau siv cais WorkStealingTaskSchedulers nyob rau hauv qhov chaw ntawm qhov kev pab cuam qhov twg kev siv ThreadPool tej zaum yuav ua phem heev thiab unpredictable.
  • QueuedTaskScheduler - tso cai rau koj ua cov haujlwm raws li cov cai tswj hwm qhov tseem ceeb
  • ThreadPerTaskScheduler - tsim cov xov sib cais rau txhua txoj haujlwm uas tau ua tiav ntawm nws. Nws tuaj yeem pab tau rau cov dej num uas siv sijhawm ntev heev los ua kom tiav.

Muaj cov ncauj lus kom ntxaws ib tsab xov xwm hais txog TaskSchedulers ntawm microsoft blog.

Kom yooj yim debugging ntawm txhua yam ntsig txog Tasks, Visual Studio muaj lub qhov rais Tasks. Hauv qhov rai no koj tuaj yeem pom lub xeev tam sim no ntawm txoj haujlwm thiab dhia mus rau txoj kab kev ua haujlwm tam sim no.

.NET: Cov cuab yeej rau kev ua hauj lwm nrog multithreading thiab asynchrony. Ntu 1

PLinq thiab Parallel class

Ntxiv rau Kev Ua Haujlwm thiab txhua yam hais txog lawv, muaj ob lub cuab yeej nthuav dav hauv .NET: PLinq (Linq2Parallel) thiab chav Parallel. Thawj zaug cog lus tias yuav ua tiav txhua qhov haujlwm Linq ntawm ntau cov xov. Tus naj npawb ntawm cov xov tuaj yeem teeb tsa siv WithDegreeOfParallelism txuas ntxiv txoj kev. Hmoov tsis zoo, feem ntau PLinq nyob rau hauv nws lub neej ntawd hom tsis muaj cov ntaub ntawv txaus hais txog lub internals ntawm koj cov ntaub ntawv qhov chaw los muab ib tug tseem ceeb ceev nce, ntawm qhov tod tes, tus nqi ntawm kev sim yog tsawg heev: koj tsuas yog yuav tsum tau hu rau AsParallel txoj kev ua ntej. cov saw ntawm Linq txoj hauv kev thiab khiav cov kev xeem ua haujlwm. Ntxiv mus, nws muaj peev xwm dhau cov ntaub ntawv ntxiv rau PLinq txog qhov xwm txheej ntawm koj cov ntaub ntawv siv lub Partitions mechanism. Koj tuaj yeem nyeem ntxiv no и no.

Chav Kawm Parallel static muab txoj hauv kev rau iterating los ntawm Foreach sau nyob rau hauv parallel, executing ib lub voj, thiab executing ntau delegates nyob rau hauv parallel Invoke. Kev ua tiav ntawm cov xov tam sim no yuav raug tso tseg kom txog thaum kev suav ua tiav. Tus naj npawb ntawm cov xov tuaj yeem teeb tsa los ntawm kev hla ParallelOptions raws li qhov kev sib cav zaum kawg. Koj tuaj yeem hais qhia TaskScheduler thiab CancellationToken siv cov kev xaiv.

tshawb pom

Thaum kuv pib sau tsab xov xwm no raws li cov ntaub ntawv ntawm kuv daim ntawv tshaj tawm thiab cov ntaub ntawv uas kuv tau sau thaum kuv ua haujlwm tom qab nws, kuv tsis xav tias yuav muaj ntau npaum li ntawd. Tam sim no, thaum cov ntawv nyeem uas kuv tab tom ntaus ntawv no reproachfully qhia kuv tias nplooj ntawv 15 tau ploj mus, kuv yuav xaus cov txiaj ntsig ib ntus. Lwm yam kev dag ntxias, APIs, cov cuab yeej pom kev thiab qhov pitfalls yuav raug them rau hauv tsab xov xwm tom ntej.

Cov lus xaus:

  • Koj yuav tsum paub cov cuab yeej rau kev ua hauj lwm nrog threads, asynchrony thiab parallelism nyob rau hauv thiaj li yuav siv cov peev txheej ntawm niaj hnub PCs.
  • .NET muaj ntau yam cuab yeej sib txawv rau cov hom phiaj no
  • Tsis yog txhua tus ntawm lawv tau tshwm sim ib zaug, yog li koj tuaj yeem nrhiav cov cuab yeej cuab tam, txawm li cas los xij, muaj txoj hauv kev los hloov APIs qub yam tsis muaj kev siv zog ntau.
  • Ua hauj lwm nrog threads hauv .NET yog sawv cev los ntawm cov chav kawm Thread thiab ThreadPool
  • Thread.Abort, Thread.Interrupt, thiab Win32 API TerminateThread txoj kev txaus ntshai thiab tsis pom zoo siv. Hloov chaw, nws yog qhov zoo dua los siv CancellationToken mechanism
  • Flow yog ib qho khoom muaj txiaj ntsig thiab nws cov khoom muaj tsawg. Cov xwm txheej uas xov tsis khoom tos rau cov xwm txheej yuav tsum zam. Rau qhov no nws yog qhov yooj yim siv chav kawm TaskCompletionSource
  • Cov cuab yeej muaj zog tshaj plaws thiab siab heev .NET rau kev ua haujlwm nrog kev sib luag thiab asynchrony yog Tasks.
  • C# async/ait operators siv lub tswv yim ntawm kev tos tsis thaiv
  • Koj tuaj yeem tswj tau qhov kev faib ntawm Tasks hla cov xov uas siv TaskScheduler-derived chav kawm
  • Tus qauv ValueTask tuaj yeem pab tau zoo hauv kev ua kom zoo ntawm cov kub-txoj kev thiab nco-tsheb
  • Visual Studio's Tasks thiab Threads windows muab ntau cov ntaub ntawv tseem ceeb rau kev debugging multi-threaded lossis asynchronous code
  • PLinq yog cov cuab yeej txias, tab sis nws yuav tsis muaj cov ntaub ntawv txaus txog koj cov ntaub ntawv, tab sis qhov no tuaj yeem kho tau siv cov txheej txheem muab faib.
  • Kom txuas ntxiv…

Tau qhov twg los: www.hab.com

Ntxiv ib saib