.NET: Instrumenta ad operandum cum multithreading et asynchronia. Pars I

Divulgo articulum originale in Habr, cuius translatio in corporate ponitur blog.

Necessitas aliquid asynchrone faciendi, non expectata hic et nunc eventum, vel magnum opus dividere in pluribus unitatibus illud faciendo, ante computatorum adventum exstitit. Horum adventu, haec necessitas valde sensibilis facta est. Nunc, anno 2019, hunc articulum typum in laptop cum processu 8-core Intel Core, in quo plus centum processus in parallelis currunt, et magis fila. Prope est telephonium sordidum leviter, abhinc duos annos emit, processus 8-core in tabula habet. Facultates thematicae plenae sunt articulis et videos ubi auctores hoc anno in smartphones praetoriae quae pluma 16-core processors mirantur. MS Azure virtualem machinam cum 20 processus nucleus praebet et 128 TB RAM minus quam $2/hora. Infeliciter, impossibile est hanc vim maximam et phaleras extrahere, quin possit tractare commercium staminum.

terminology

Processus - OS obiectum, spatium inscriptionis solitariae, stamina continet.
Thread - obiectum OS, minima unitas executionis, pars processus, fila memoriam participant et aliae facultates intra processum inter se.
multitasking - OS proprietas, facultas plures processus simul currere
Multi-core - proprietas processus, facultas utendi plures coros pro MGE
Multiprocessing - Proprietas computatralis, facultas simul cum pluribus processoribus corporaliter operari
Multithreading - proprietas processus, facultas distribuendi MGE inter plura fila.
Parallelismus - faciendo plures actiones corpore simul per unitatem temporis
Asynchrony - Executio alicuius operationis non expectata huius processus complementum, effectus exsecutionis postea discursum est.

metaphora

Non omnes definitiones bonae sunt et explicatione aliqua egent addita, ideo metaphoram de ientaculo coquendo terminologiae formaliter introductam addam. In hac metaphora ientaculum coquere est processus.

Dum prandium mane parat (cpuad culinam veniocomputatrum). Habeo II manus (millia metretas). Plures machinis in culina sunt.IO): clibanus, ahenum, toaster, leo. Ego in felis converto, in ea sartagine pone et infunde oleum sine exspectatione ut calefiat;asynchronously, Non Clausus-IO-Expectate) Ova e armario accipio et in patinam frango, deinde una manu percutiam (Post # 1) et secundus (Post # 2) laminam tenens (Shared Resource). Nunc in ahenum vertere vellem, sed mihi manus satis non est.Post Starvation) Hoc tempore sartagine calefacit in quam effundo quod flagellavi. Pervenio ad lebetem et verto illud et stolide in aqua coques speculare (Clausus-IO-Expectate) , licet hoc tempore laminam lavare posset ubi omelet flagellabat.

Coxi omelette tantum utens 2 manibus, et non plus habeo, sed simul, in articulo uerberum omelette, 3 operationes statim fiebant: uerbera omelette tenentem laminam, sartagine calefacit. CPU pars est velocissima computatoris, IO est quod saepissime omnia retardat, toties solutio efficax CPU aliquid occupare cum notitia ab IO accipienda est.

Metaphora continuans;

  • Si in processu parandi omelet, etiam vestes mutare conari, hoc exemplum multitasking esset. Magni momenti nuance: computatores multo meliores sunt in hoc quam homines.
  • Culina cum pluribus obsonatoribus, exempli gratia in caupona - multi-core computatrum.
  • Multi popinae in atrio cibum in shopping centrum - Mauris interdum

.NET Tools

.NET bonum opus cum filis, ut cum multa alia. Cum unaquaque nova versione, magis magisque nova instrumenta ad operandum cum illis inducit, novas abstractionis stratas super OS filis. Cum operando cum constructione abstractorum, tincidunt compage accessu utantur qui occasionem relinquit, cum abstractio alta utitur, ad unum vel plures gradus infra descendendum. Saepissime hoc non est necessarium, etenim ianuam aperit ut te in pede cum pyrobolo figas, sed interdum, in raro casu, sola quaestio solvenda est quae in gradu abstractionis non solvitur. .

Per instrumenta, tum applicationis programmandi interfaces (APIs) intelligimus a compage et fasciculis tertia partium instructum, necnon solutiones integras programmatum quae simpliciorem investigationem pro quibusvis quaestionibus ad multi-lineatum codicem pertinentibus significamus.

Satus filo

Classis sequela est fundamentalissimum genus in .NET ad operandum cum filis. Fabricator unum ex duobus delegatis accipit;

  • ThreadStart - Nulla parametri
  • ParametrizedThreadStart - uno modulo objecti generis.

Delegatus in filo novo creato post modum Satus vocato perficietur: Si delegatus typorum Parametrised ThreadStart ad conditorem transiit, objectum ad methodum Initium transeundum est. Haec machina necessaria est ad informationes locales ad rivum transferendas. Notatu dignum est quod stamina creans operationem pretiosam est, et ipsum filum grave est, saltem quia 1MB memoriae in ACERVUM collocat et commercium cum API OS requirit.

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

Classis piscinae conceptum stagni significat. In .NET, sequela piscine pars machinalis est, ac tincidunt Microsoft in multa opera posuerunt ut certa opera optime in diversis missionibus operaretur.

Notio generalis:

Ex tempore applicationis incipit, plura fila in subsidiis in campo creat et facultatem praebet ad usum capiendi. Si stamina frequenti et frequenti adhibita sunt, stagnum dilatatur ad necessitates salutantis. Stamina cum in piscina non sint tempore opportuno, aut unum e staminibus exspectabit ut revertatur, aut novum creabit. Sequitur ut stamina piscinae magnae sint ad breve tempus actiones quaedam et male apta operationibus quae per totam operationem applicationis officia currunt.

Filo e stagno utendo, modus est QueueUserWorkItem, qui delegatum type WaitCallback accipit, qui eandem obsignationem habet ac ParametrizedThreadStart, et parametri ad illud munus idem fungitur.

ThreadPool.QueueUserWorkItem(...);

Modus phialis filorum minoris notus RegisterWaitForSingleObject adhibetur ad operationes non-obstructiones IO ordinandas. Delegatus ad hanc methodum transiens vocabitur cum WaitHandle ad modum "Dimissi" transiit.

ThreadPool.RegisterWaitForSingleObject(...)

.NET fila timer habet et a WinForms/WPF timers differt quod eius tracto in filo e lacu vocabitur.

System.Threading.Timer

Est etiam via magis exotica ut delegatum ad executionem ad filum e stagno mittat - the method BeginInvoke.

DelegateInstance.BeginInvoke

Breviter immorari velim de munere ad quod multi methodi praedictarum dici possunt - CreateThread from Kernel32.dll Win32 API. Est via, per mechanismum methodorum externarum, quae hoc munus vocant. Talem vocationem vidi semel tantum in gravi exemplo codicis legati, et motiva auctoris qui hoc prorsus fecit, mysterium mihi adhuc manet.

Kernel32.dll CreateThread

Videre et Debugging Threads

Fila a te condita, omnes partes tertiae partis, et .NET piscina spectari possunt in fenestra sequelarum Studiorum Visualis. Haec fenestra solum informationes sequelae ostendet cum application sub debug et in modum Break. Hic commode potes nomina ac potiora singulorum filorum intueri, ac debugging ad certa fila flectere. Prioritate possessionis Thread genus utens, prioritatem sequelae, quam OC et CLR pro commendatione percipiet, cum processor temporis inter fila dividens.

.NET: Instrumenta ad operandum cum multithreading et asynchronia. Pars I

Negotium Parallel Library

Task Bibliotheca Parallel (TPL) introducta est in NET 4.0. Est autem vexillum et principale instrumentum ad asynchroniam operandam. Cuilibet codice, quo vetustiore utitur, accedere legatum putatur. Praecipua unitas TPL est Negotium genus e System.Threading.Tasks spatio nominali. Negotium est abstractio super filo. Cum nova versionis linguae C#, eleganter cepimus modum operandi cum Tasks - async/expectantibus operariis. Haec notiones efficere potuit ut codicem asynchronum scriberet quasi simplex et synchronum, hoc effecit ut homines minus intellegentes internas sequelarum sequelam ad applicationes utentes utentes scriberent, applicationes quae diu operationes exercentes non gelescunt. Usura async/exspectare est thema unius vel etiam plurium articulorum, sed experiar summam eius paucis sententiis:

  • async est determinatio methodi reddens Negotium vel vacui
  • et exspectatio non-obturans Negotium exspectans operator est.

Iterum: opperiens operator, in generali casu (excipiuntur), current stamen executionis iterum solvet, et cum Negotium suum exsecutionem finiet, et filum (re vera, rectius dicendum erit contextus. sed plura in eo postea) modum ulterius exequendi perseueret. Intra .NET, haec mechanismus perficitur eodem modo ac reditus cede, cum methodus scripta in totum genus vertit, quod est machina publica et in singulis partibus secundum has Civitates exsecutioni mandari potest. Quilibet interest scribere aliquem codicem simplicem utentem asynс/exspectare, compilare et videre conventum utens JetBrains dotPeek cum Compiler Codice generato para.

Intueamur ad optiones deducendi et utendi Negotium. In codice infra exemplo, novum negotium creamus quod nihil utile facitThread.Sleep ((X))) sed in vita reali hoc opus esse debet CPU intensivum complexum.

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
}

Negotium creatur cum numero optionum;

  • LongRunning admonitus est negotium non cito perficiendum, quod significat considerare non posse linum e stagno, sed unum separatum creare pro hoc Negotium ut aliis non laedat.
  • Adnexa ToParent - Negotium in hierarchia disponi potest. Si haec optio adhibita est, Negotium potest esse in eo statu ubi ipsa complevit et filiorum suorum exsecutionem exspectat.
  • PreferFairness - significat melius esse ut Tasks exsecutioni mandari prius quam postea missi sunt. Sed hoc solum commendationis et eventus non praestatur.

Secundus modulus ad methodum CancellationToken transiit. Ad recte tractandum indultum operandi, postquam incepit, codicem exsecutioni mandari ob impedimentis statui Cancellation- token implendum est. Si impedimenta non sunt, tunc Modus Abrigavi vocatus in obiecto CancellationTokenSource exsecutionem Negotium prohibere poterit nisi antequam inceperit.

Ultima parameter est obiectum schedularum speciei TaskScheduler. Haec classis eiusque posteri ad consilia moderanda destinata per fila distribuenda sunt, per defaltam, Negotium in temere filo e stagno fiet.

Operator opperiens applicatur ad Negotium creatum, quod significat codicem post illum inscriptum, si adsit, in eodem contextu futurum (saepe hoc modo in eodem sequela) ac signum ante exspectamus.

Modus async vacui designatus est, quo significat uti insidiator operator potest, sed vocatio signum executioni expectare non poterit. Si talis factura necessaria est, ratio reddendi Negotium est. Methodi async vacui notati satis communes sunt: ​​ut regula, hae sunt tractores eventus vel alii modi qui in igne laborant et principium obliviscuntur. Si opus est non solum occasionem dare usque ad finem executionis exspectare, sed etiam effectum reddere, tunc opus est ut Task.

In Negotio quod methodus startNew redierat, sicut et in quavis alia, methodum ConfigureAwait cum falso parametro appellare potes, tum exsecutio post exspectationem non in contextu captum, sed in arbitrario permanebit. Hoc semper fieri debet cum contextus exsecutionis non refert pro codice post exspectationem. Haec etiam commendatio ex MS cum codice scripto tradetur quod in bibliotheca fasciculatum erit.

Aliquantum inhabitemus quonam modo expletionem operis expectare possis. Infra exemplum codicis est, cum commentatur de conditione bene et cum conditione male fit exspectatio.

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
}

In primo exemplo Negotium exspectamus ut sine obstaculo vocationi stamina perficiat, ad effectum deducendum solum cum iam est revertemur, donec tunc vocatio filum suis machinis relinquitur.

In secunda optione, filum vocationi praecludimus donec methodus computata sit. Hoc malum est non solum quod filam occupavimus, tam valida progressionis copia, cum simplici otio, sed etiam quia, si modus quem vocamus contineat codicem exspectamus, contextus synchronisation postulat ut ad vocationem sequelam revertamur. exspectamus, tunc mortificationem dabimus. Vocatio filum asynchronae methodi calculandi exitum expectat, methodus asynchrona in stamine vocationis suam executionem frustra continuare conatur.

Aliud incommodum accessionis erroris perplexus tractatio est. Re vera errores in codice asynchrono cum adhibitis async/is exspectantibus facillime sunt tractandi - perinde se habent ac si codex synchronus esset. Dum si exorcismum adhibemus synchronum ad Negotium exspectandum, prima exceptio fit in aggregationem Exceptionis, i.e. Ad exceptionem tractandam, genus InnerExceptionis examinare debebis et scribe si catenam te intra unum capeolum vel clausuram capiendo uteris, pro vinculo capturae caudices familiarioris in C# mundo.

Tertia et ultima exempla etiam ob eandem causam notata sunt mala, eademque omnia problemata continent.

The CumAny and Cum Omnia methodi apprime commoda sunt ad exspectationem coetus Tasks, coetus Tasks in unum involvunt, qui incendent aut cum Negotium e coetu primum Urguet, aut cum omnes exsecutionem expleverunt.

Restitit relatorum

Propter varias causas, necesse est ut fluere desinat postquam incepit. Pluribus modis hoc facere. Genus sequela duos modos convenienter nominatos habet: Abortus и PRAECIDO. Primum valde non commendatur usui, quia quovis momento advocato, in processu alicujus instructionis, excipitio mittetur ThreadAbortedException. Non expectas talem exceptionem eiici cum incremento cuiuslibet integer variabilis, ius? Et cum hac ratione utens, hoc verissimum est. Si CLR hanc exceptionem in certa codicis sectione generare prohibere debes, eam in vocationibus involvere potes Thread.BeginCriticalRegion, Thread.EndCriticalRegion. Quodlibet codicem scriptum in stipitem tandem tali vocatione involutum est. Quam ob rem in ima compage codicis invenire potes caudices inani conatu, sed non inani tandem. Microsoft hanc methodum adeo dehortatur ut eam in nucleo retiali non comprehendant.

Methodus interpellandi praevidere magis operatur. Potest interrumpere stamina cum exceptione ThreadInterruptedException tantum per momenta illa, cum filum in statu exspectans est. Hunc statum intrat dum pendens exspectans WaitHandle, seram vel post vocatum Thread.Sleep.

Utrumque optiones supra scriptas malae sunt propter eorum unpredictability. Solutio est uti structura CancellationToken et classis CancellationTokenSource. Punctum est hoc: instantia Cancellationis classis creatur et solus qui habet, potest prohibere operationem vocando modum. Cancel. Solus Cancellatio Token ad ipsam operationem transmittitur. Dominis receptae non possunt ipsam operationem exstinguere, sed solum reprehendo an operatio abolita sit. Hoc est proprium Boolean IsCancellationRequested et methodo ThrowIfCancelRequested. Haec exceptio mittet TaskCancelledException si Modus Abrigavi vocatus est in Instantia Cancellation-token parrota. Atque haec est ratio utendi commendo. Haec emendatio est in optiones superiores, dum plenam potestatem obtinet in quo puncto operatio exceptionis abortivi esse potest.

Optionem crudelissimam sistendi filo est munus vocare Win32 API TerminateThread. Mores CLR vocato hoc munere vagus esse possunt. Die MSDN scriptum est sequenti de hoc munere; “TerminateThread munus periculosum est quod in maximis casibus tantum uti debet. "

Convertere legatum API ad Negotium Substructio utendi FromAsync methodo

Si fausta es satis operari in incepto quod inceptum est postquam Tasks introducta est et cessavit horrorem quietum facere in plerisque tincidunt, tunc non habebis multum agere cum antiquis APIs, et tertia-pars et cum quadrigis tuis. in praeteritum iam excrucior. Feliciter, .NET Framework manipulus nos curabat, quamquam fortasse propositum nobis curandum erat. Esto ut fortasse, .NET plura instrumenta ad codicem vetustum asynchronum programmandi ad novum novum accedens asynchronum convertendi sine dolore scriptum habet. Una earum est methodus FromAsync TaskFactory. In codice infra exemplum, veteres methodos async genus WebRequest involvo in hac ratione utens.

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

Hoc solum exemplum est, et tu credibile est hoc facere cum in typis constructis, sed quodlibet vetus consilium simpliciter scatentem cum BeginDoSomething methodi redeuntes IAsyncResult et EndDoSomething methodi quae recipiunt.

Convoco legatum API ad Task Substructio per TaskCompletionSource classis

Alius instrumentum magni momenti considerare est genus TaskCompletionSource. Secundum functiones, propositum et principium operandi, aliquid simile esse potest in RegisterWaitForSingleObject methodi Thread Pool classis, de qua supra scripsi. Hoc genere utens, facile et commode vetus APIs asynchronum in Tasks involvere potes.

Dices me iam locutum esse de methodo FromAsync classium TaskFactorii ad haec destinata. Hic memorare debebimus totam historiam evolutionis exemplorum asynchronorum in reticulo quem Microsoft obtulerit per XV annos praeteriti: ante Task-Substructum Pattern Asynchronum (TAP), exemplar programmandi Asynchroni (APP), quod modi erat incipeDoSomething reverti IAsyncResult et modos finisDoSomething acceptare et pro legato horum annorum methodus FromAsync iusta perfecta est, sed super tempus, eventum Substructio Asynchronous Pattern substitutum est.EAP) , quod asynchronum expletum fore eventum assumpsit.

TaskCompletionSource perfectus est ad involutionem Tasks et legatum APIs circa eventum exemplar aedificatum. Essentia operis eius est haec: obiectum huius ordinis publicas proprietates generis Negotium habet, cuius status per SetResult, SetException, etc methodos TaskCompletionSource classium gubernari potest. In locis ubi exspectator operator huic Task applicatus est, fiet vel deficiat exceptio secundum modum quod TaskCompletionSource applicatum est. Si nondum liquet, exemplum inspiciamus hoc codice, ubi vetus aliquod EAP API in Opere usus TaskCompletionSource involvitur: cum eventus ignes, Negotium in statum perfectum transferetur, et modum quem exspectantis operantis applicavit. huic Negotium repetet executioni obiecto accepto exitum.

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

Involutio vetus APIs non est omnia quae fieri possunt utendo TaskCompletionSource. Utens hoc genus aperit interesting possibilitas APIs varias cogitandi in Tasks quae fila non tenent. Et fluvius, ut meminimus, res pretiosa est eorumque numerus circumscribitur (maxime per quantitatem RAM). Haec limitatio facile perfici potest per evolutionem, exempli gratia, applicationem telam onustam cum logica multiplici negotio. Consideremus facultates quas loquor de cum exsequendo talem dolum sicut Long-Polling.

In summa, essentia doli haec est: informationes accipere debes ab API de aliquibus eventibus in eius latere occurrentibus, dum API aliqua de causa referre non possunt eventum, sed solum statum referre possunt. Horum exemplum omnes APIs super HTTP supra tempora WebSocket aedificati sunt vel cum hac technica ratione uti impossibile est. Cliens HTTP servo petere potest. Servus HTTP non potest communicationem cum cliente inire. Simplex solutio est servo utentem timer tondere, sed hoc onus additicium facit in servo et additam moram in mediocris TimerInterval / 2. Ad hoc circumveniendum inventa est fraus quae Long Polling vocatur, quae responsionem ab mora differens involvit. server usque ad Timeout expirat vel eventus erit. Si res incidit, tunc discursum est, sin minus, petitio iterum remissa est.

while(!eventOccures && !timeoutExceeded)  {

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

Sed talis solutio mox erit terribilis numerus clientium exspectantium eventum, quod... Quisque talis cliens totum filum occupat eventum exspectans. Ita, ac moram 1ms adiectis consequimur, cum res utitur, frequentius hoc non significat, sed cur uter plus quam esse potest? Si Thread.Sleep removemus (1), frustra tunc unum processum nucleum 100% otiosum oneremus, in inani cyclo circumabimur. Usura TaskCompletionSource facile hunc codicem reformare potes et omnes quaestiones supra identificas solve:

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

Hoc signum productio-parata non est, sed solum demo. Uti in realibus casibus, necesse est, minimum, tractare condicionem cum nuntius pervenit ad tempus quo nemo id exspectat: hoc in casu, AsseptMessageAsync methodus iam peracta Negotium reddere debet. Si hoc frequentissimum est, tunc de utendo ValueTask cogitare potes.

Cum petitionem pro nuntio accipimus, TaskCompletionSource in dictionario creamus et collocamus, deinde expectamus quid primum fiat: tempus determinatum exspirat aut nuntium recipitur.

ValueTask: quare et quomodo

Async/exspectare operariorum, sicut fructus reditus operantis, machinam publicam ex methodo generant, et haec est creatio novi obiecti, quod fere semper non est magni momenti, sed in raro casu problema creare potest. Hic casus potest esse methodus, quae saepe vere dicitur, loquimur de decem et centenis milibus appellationum per alterum. Si talis methodus ita scripta est ut in pluribus eveniat praetermittendis omnibus modis exspectandis, tunc .NET instrumentum praebet ad hoc optimizandum - ValueTask structuram. Ut pateat, exemplum usus eius inspiciamus: est cella quam persaepe imus. Quaedam bona sunt in ea, et tunc simpliciter reddamus ea: sin minus, ad aliquas tardiores IO perveniamus. Posteriorem asynchronose facere volo, quod significat totam methodum asynchronam evadit. Sic tibi evidens modus scribendi talis est;

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

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

Propter desiderium optimize modice, et levis timor quid Roslyn generabit cum hoc codice componendo, hoc exemplum rescribere potes hoc modo:

public Task<string> GetById(int id) {

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

Re quidem vera solutio huius rei optimalis esset iter calidum optimize, nempe valorem obtinendum ex dictionario sine prouinciis superfluis et onere GC, cum in illis raris casibus, cum adhuc opus est ad IO pro notitia adire. omnia restant plus /minus vetustate;

public ValueTask<string> GetById(int id) {

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

Propius hanc partem codicis inspiciamus: si pretium est in cella, structuram facimus, alioquin negotium reale significanti involvetur. Vocatio codicis non curat quam viam in hoc codice peractum sit: ValueTask, ex parte C# syntaxis, idem erit ac regulariter in hoc casu.

TaskSchedulers: negotium administrandi Lorem strategies

Proximus API quod considerare velim est genus TaskScheduler eiusque derivatis. Iam supra dixi TPL facultatem administrandi consilia ad pensas trans fila distribuendi. Huiusmodi consilia in posteris classis TaskScheduler definiuntur. Fere quodlibet consilium in bibliotheca inveniri potest. ParallelExtensionsExtras, evoluta Microsoft, sed non pars .NET, sed involucrum Nugeti subministratum. Breviter aliqua ex eis inspiciamus:

  • CurrentThreadTaskScheduler - facit Tasks in current filum
  • LimitedConcurrencyLevelTaskScheduler — numerus Tasks finitus eodem tempore a parametro N, qui in constructor acceptus est
  • OrderedTaskScheduler - definitur ut LimitedConcurrencyLevelTaskScheduler(1), ita opera sequentially exsecuta erunt.
  • WorkStealingTaskScheduler - implements opus-furari accedere ad negotium distributionis. Essentialiter separatum est ThreadPool. Solvit problema quod in .NET Thread Pool genus static est, unum pro omnibus applicationibus, quod significat eius obrutionem vel non rectam usum in una parte progressionis ad effectus in alia parte ducere posse. Horum autem defectuum causam cognoscere difficillimum est. Quod. Opus esse potest ut WorkStealingTaskSchedulers separatos in partibus programmatis, ubi usus ThreadPool ferox et vagus esse potest.
  • QueuedTaskScheduler - sino vos praestare officia secundum prius queue praecepta
  • ThreadPerTaskScheduler - singula fila efficit pro unoquoque Negotium quod in eo exercetur. Utile esse potest ad opera quae inaestimabile est longum tempus ad perficiendum.

Est bonum detailed articulus de TaskSchedulers in Microsoft blog.

Pro opportunitate debugging omnium ad Tasks pertinentium, Visual Studio munus fenestrae habet. In hac fenestra videre potes statum hodiernam muneris ac salire ad praesentem codicem exsequentem.

.NET: Instrumenta ad operandum cum multithreading et asynchronia. Pars I

PLinq and the Parallel class

Praeter Tasks et omnia de illis dicta, duo instrumenta magis interesting in .NET: PLinq (Linq2Parallel) et classis Parallel. Prima promittit parallela exsecutio omnium Linq operationum in filis multiplicibus. Numerus sequelarum configurari potest utens methodo extensionis WithDegreeOfParallelismi. Infeliciter, frequentius PLinq in modo suo defectu non habet satis informationem de internis tuis notitiarum fonte ad notabilem celeritatem quaestum praebendum, contra, sumptus tentandi valde humilis est: tu modo ante methodum AsParallel vocare debes. catenae Linq modos ac currunt perficiendi probat. Praeterea praeterire potest informationis informationes ad PLinq de natura notitiarum vestrarum fonte utens in partitionibus mechanismum. Potes legere plus hic и hic.

Classis static genera praebet rationes iterandi per collectionem Foreach in parallelis, exsequens Pro loop, et plures delegatos in parallela Invoke exequens. Executio sequelae hodiernae obstruetur donec calculi perficiantur. Numerus sequelarum configurari potest obiter parallelOptiones ut ultimum argumentum. Specificare etiam potes TaskScheduler et CancellationToken utentes optiones.

Inventiones

Cum hunc articulum scribere coepi ex materia relationis meae et percontationes quas in opere meo collegi post illum, non exspectavi tantum de eo futurum esse. Nunc, cum textus editor in quo hunc articulum typingo contumeliose narrat mihi pagina 15 discessisse, eventus interim compendiam. Aliae strophae, APIs, instrumenta visualia et foveae proximo articulo erunt.

conclusiones:

  • Scire debes instrumenta ad operandum cum filis, asynchronis et parallelismo ut opibus recentiorum PCs utaris.
  • .NET multa instrumenta diversa ad haec proposita
  • Non omnes statim apparuerunt, ut saepe invenire possis legata, tamen sunt modi veteres APIs convertendi sine magno labore.
  • Stamina in .NET, sequela ac ThreadPool classes
  • Thread.Abort, Thread.Interrupt, et Win32 API TerminateThread methodi periculosae sunt et usui non commendantur. Sed melius est uti mechanismo CancellationToken
  • Fluxus validus subsidio est eiusque copia limitatur. condiciones ubi sequelae occupantur exspectationes eventus vitandae sunt. Hoc enim commodum est uti genere TaskCompletionSource
  • Potentissima et provecta .NET instrumenta ad operandum cum parallelismo et asynchronia sunt Tasks.
  • In c# async/expectantibus notionem efficiendi operatorium non-obturans interclusio
  • Distributionem Tasks trans fila temperare potes utendo classes TaskScheduler-deductae
  • The ValueTask structura utilis esse potest in callibus optimizing calidis et negotiationibus scientificis
  • Visual Studio's Tasks et Sequelae fenestrae multum utiles praebent informationes ad debugging multi-filam vel asynchronum codicem
  • PLinq instrumentum frigidum est, sed satis compertum est de fonte notitiarum tuarum non habere, sed hoc figi potest utens partiendi mechanismum
  • Ut continued ...

Source: www.habr.com

Add a comment