Тази статия е огледална статия за машинен превод, моля, кликнете тук, за да преминете към оригиналната статия.

Изглед: 15343|Отговор: 2

[Комуникация] [превод]. NET за използване на разликата между ValueTask и Task

[Копирай линк]
Публикувано на 2022-3-17 11:21:50 | | | |


Използването на Task или Task класове има ограничение в производителността, което не споменахме в предишните статии. Накратко, тези класове водят, когато резултатите са веднага наличниНенужно разпределение。 Това означава, че винаги ще бъде създаден нов обект Задача или Задача, дори ако резултатът вече е наличен. Споменахме, че концепцията async/await, която използвахме в предишните статии, съществува още от излизането на .NET 4.5. Тази функция е подобрена от C# 7 с .NET 4.7 версията със структурата ValueTask, която може да се използва като връщане за асинхронни функции.

Структура на ValueTask


Структурата ValueTask се появи за първи път в хранилището corefxlab през 2015 г. Това хранилище се използва за експериментиране и изследване на нови идеи, които може да стигнат или да не стигнат до основния репозиториум на corefx. Репозиториумът Corefx е хранилището, където се намират всички базови библиотеки на .NET Core. Тя беше разработена и предложена от Стивън Тауб за библиотеката System.Threading.Tasks.Channels. Тогава Стивън даде кратко обяснение:

Адрес на библиотеката CorefxLab:Входът към хиперлинк е видим.


ValueTask е отделно обединение на T и Задача, което позволява на ReadAsync свободно да разпределя и синхронно връща наличните си T стойности (за разлика от използването на Task.FromResult, което изисква разпределение на инстанция на задача). ValueTask е изчакваем, така че потреблението на повечето случаи е неразличимо от консумацията на задачи.
Много хора виждат ползите от използването на тази структура, която е включена в C# 7 като част от пакета System.Threading.Tasks.Extensions NuGet. Преди да се потопим в структурата на ValueTask, нека разгледаме проблема, който тя решава. Тъй като Task(Task) е референтен тип, започнете сАсинхронният метод, който връща обекта Задача, означава, че той се заделя на купчината всеки път。 Това е необходимо в много случаи.

Въпреки това, в някои случаи асинхронните методи връщат резултати веднага или завършват синхронно. В тези случаи това разпределение е излишно и може да стане скъпо в критични за производителността части на кода. До изданието на .NET 4.7 нямаше начин да се избегне това, тъй като асинхронните методи трябваше да връщат Task, <T>Task или void (последното обикновено беше нежелателно). В тази версия на .NET това е разширено, което означава, че асинхронен метод може да върне всеки тип, стига да има достъпен метод GetAwaiter. ValueTask е конкретен пример за този тип и също беше добавен към това издание.

Можете да разгледате репозиториума на Corefx и да видите пълната реализация на ValueTask, ето секцията с API, която ни интересува:



Като структура, ValueTask позволява писане на асинхронни методи, които не заделяват памет по време на синхронно изпълнение. Консистентността на API на концепцията async/await не се компрометира по този начин. Освен това, тази структура чака сама, което я прави лесна за използване. Например, ако изпълним този прост код:

В метода MultiplyAsync симулираме ситуация, в която искаме да избегнем използването на Task и да върнем само обикновено цяло число. Това се прави в if-оператора на метода, където по същество проверяваме дали похвърленият параметър е нула. Проблемът еДори ако нашето условие в ако е вярно, горният код създава обект Задача。 Решаваме този проблем по следния начин:

СтойностЗадача и Задача



Както беше споменато по-рано, има две основни ползи от използването на ValueTask:

  • Подобрения в производителността
  • Увеличаване на гъвкавостта при внедряване


И така, какви са числата зад подобренията в производителността? Спазвайте този код:


Ако изпълним този код, JIT-ът се изпълнява от 120 нс. Сега, ако заменим Task със ValueTask по следния начин:

С JIT ще получим време за изпълнение от 65ns. Вярно е, че поради Task.Delay не изпълняваме синхронно, но виждаме подобрение във времето за изпълнение.

Друго предимство, което споменахме, е повишената гъвкавост в изпълнението. Сега, какво точно означава това? Реализациите на асинхронни интерфейси, които трябва да бъдат синхронизирани, ще бъдат принудени да използват Task.Run или Task.FromResult. Разбира се, това води до проблемите с представянето, които обсъдихме по-рано. Когато използваме ValueTask, по-вероятно е да избираме между синхронни или асинхронни реализации. Имайте предвид, че това може да е знак, че кодът ви може да не е добре проектиран, ако това ви се случи.

Например, наблюдавайте този интерфейс:


Да кажем, че искате да го наречете от код по следния начин:

Тъй като използваме ValueTask в интерфейса, реализацията на интерфейса може да бъде синхронна или асинхронна. Можем да получим тази полза, като просто пропуснем добавянето на някои функции към IThing, които управляват синхронизиращото поведение. Много по-лесно е да се използва този интерфейс по този начин. Ето синхронна реализация на горния интерфейс:

Ето асинхронна реализация на същия интерфейс:

Въпреки това, трябва да обмислим някои компромиси, преди да използваме ValueTask. Лесно е да се мисли, че по подразбиране трябва да се използва ValueTask вместо Task, което определено не е така. Например, въпреки че ValueTask ни помага да избегнем ненужни присвоявания, когато е налична синхронизация на резултатите, той съдържа и две полета.

Важно е да помним, че това е структурата, която използваме тук, което означава, че използваме типове стойности и всички техни тежести. Задачата, от друга страна, е референтен тип с само едно поле.Когато използвате ValueTask, имаме повече данни за обработка и обработка. Ако такъв метод се чака при асинхронен метод, тогава асинхронният метод еСъстоянията също ще бъдат по-големи, защото съхраняването на цялата структура обикновено изисква повече пространство, отколкото съхраняването на една единствена референция.

Затова хората от Microsoft всъщност препоръчват да се използва Task или Task като стандартен тип връщане за асинхронни методи. Едва след анализ на производителността трябва да обмислите преминаване към ValueTask.


резюме

ValueTask е структура, въведена в .NET 4.7, която ни дава много възможности за използване на асинхронни методи в .NET. Въпреки това, това не е без цена. Това е полезно при критични за производителността методи, които се изпълняват синхронно. С тях можем да избегнем разпределянето на ненужни обекти. Въпреки това, като тип стойност, той носи всички проблеми, които обикновено имат типовете стойности. Затова можем да се възползваме от тази структура, но трябва да бъдем внимателни.

Оригинален адрес:Входът към хиперлинк е видим.




Предишен:【Practical Action】Използвайте Docker за изграждане на IPsec VPN сървър
Следващ:Обърни се към OpenConnect вместо Cisco AnyConnect, за да избегнеш маршрутизиране на заключвания на таблици
Публикувано на 2022-3-18 22:21:57 |
Ела да научиш отново.
Публикувано на 22.03.2022 14:05:53 |
Научете същността на ученетоНе е лошо
Отричане:
Целият софтуер, програмни материали или статии, публикувани от Code Farmer Network, са само за учебни и изследователски цели; Горното съдържание не трябва да се използва за търговски или незаконни цели, в противен случай потребителите ще понесат всички последствия. Информацията на този сайт идва от интернет, а споровете за авторски права нямат нищо общо с този сайт. Трябва напълно да изтриете горното съдържание от компютъра си в рамките на 24 часа след изтеглянето. Ако ви харесва програмата, моля, подкрепете оригинален софтуер, купете регистрация и получете по-добри услуги. Ако има нарушение, моля, свържете се с нас по имейл.

Mail To:help@itsvse.com