.NET: Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ. Π§Π°ΡΡ‚ΡŒ 1

ΠŸΡƒΠ±Π»ΠΈΠΊΡƒΡŽ Π½Π° Π₯Π°Π±Ρ€ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π» ΡΡ‚Π°Ρ‚ΡŒΠΈ, ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ Π² ΠΊΠΎΡ€ΠΏΠΎΡ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΌ Π±Π»ΠΎΠ³Π΅.

ΠΠ΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ Π΄Π΅Π»Π°Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ асинхронно, Π½Π΅ доТидаясь Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ здСсь ΠΈ сСйчас, ΠΈΠ»ΠΈ Ρ€Π°Π·Π΄Π΅Π»ΡΡ‚ΡŒ Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΌΠ΅ΠΆΠ΄Ρƒ нСсколькими Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰ΠΈΠΌΠΈ Π΅Π΅ Π΅Π΄ΠΈΠ½ΠΈΡ†Π°ΠΌΠΈ Π±Ρ‹Π»Π° ΠΈ Π΄ΠΎ появлСния ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€ΠΎΠ². Π‘ ΠΈΡ… появлСниСм такая Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ стала ΠΎΡ‡Π΅Π½ΡŒ ΠΎΡ‰ΡƒΡ‚ΠΈΠΌΠΎΠΉ. БСйчас, Π² 2019, набирая эту ΡΡ‚Π°Ρ‚ΡŒΡŽ Π½Π° Π½ΠΎΡƒΡ‚Π±ΡƒΠΊΠ΅ с 8 ядСрным процСссором Intel Core, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ этому Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½Π΅ ΠΎΠ΄Π½Π° сотня процСссов, Π° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΈ Ρ‚ΠΎΠ³ΠΎ большС. Рядом, Π»Π΅ΠΆΠΈΡ‚ ΡƒΠΆΠ΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚Ρ€Π΅ΠΏΠ°Π½Π½Ρ‹ΠΉ, ΠΊΡƒΠΏΠ»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠ°Ρ€Ρƒ Π»Π΅Ρ‚ Π½Π°Π·Π°Π΄ Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½, Ρƒ Π½Π΅Π³ΠΎ Π½Π° Π±ΠΎΡ€Ρ‚Ρƒ 8 ядСрный процСссор. На тСматичСских рСсурсах ΠΏΠΎΠ»Π½ΠΎ статСй ΠΈ Π²ΠΈΠ΄Π΅ΠΎ, Π³Π΄Π΅ ΠΈΡ… Π°Π²Ρ‚ΠΎΡ€Ρ‹ Π²ΠΎΡΡ…ΠΈΡ‰Π°ΡŽΡ‚ΡΡ флагманскими смартфонами этого Π³ΠΎΠ΄Π° ΠΊΡƒΠ΄Π° ставят 16Ρ‚ΠΈ-ядСрныС процСссоры. MS Azure прСдоставляСт ΠΌΠ΅Π½Π΅Π΅ Ρ‡Π΅ΠΌ Π·Π° 20$/час Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΌΠ°ΡˆΠΈΠ½Ρƒ со 128 ядСрным процСссором ΠΈ 2 TB RAM. К соТалСнию Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ максимум ΠΈ ΠΎΠ±ΡƒΠ·Π΄Π°Ρ‚ΡŒ эту ΠΌΠΎΡ‰ΡŒ Π½Π΅ умСя ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ взаимодСйствиСм ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

ВСрминология

ΠŸΡ€ΠΎΡ†Π΅ΡΡ (Process) β€” ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ОБ, ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ адрСсноС пространство, содСрТит ΠΏΠΎΡ‚ΠΎΠΊΠΈ.
ΠŸΠΎΡ‚ΠΎΠΊ (Thread) β€” ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ОБ, наимСньшая Π΅Π΄ΠΈΠ½ΠΈΡ†Π° выполнСния, Ρ‡Π°ΡΡ‚ΡŒ процСсса, ΠΏΠΎΡ‚ΠΎΠΊΠΈ дСлят ΠΏΠ°ΠΌΡΡ‚ΡŒ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ рСсурсы ΠΌΠ΅ΠΆΠ΄Ρƒ собой Π² Ρ€Π°ΠΌΠΊΠ°Ρ… процСсса.
ΠœΠ½ΠΎΠ³ΠΎΠ·Π°Π΄Π°Ρ‡Π½ΠΎΡΡ‚ΡŒ β€” свойство ОБ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ нСсколько процСссов ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ
ΠœΠ½ΠΎΠ³ΠΎΡΠ΄Π΅Ρ€Π½ΠΎΡΡ‚ΡŒ β€” свойство процСссора, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ нСсколько ядСр для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…
ΠœΠ½ΠΎΠ³ΠΎΠΏΡ€ΠΎΡ†Π΅ΡΡΠΎΡ€Π½ΠΎΡΡ‚ΡŒ β€” свойство ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с нСсколькими процСссорами физичСски
ΠœΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ β€” свойство процСсса, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ€Π°ΡΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅ΠΆΠ΄Ρƒ нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ.
ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ β€” Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… дСйствий физичСски ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Π² Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ
ΠΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒ β€” Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π±Π΅Π· оТидания окончания Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ этой ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΆΠ΅ выполнСния ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ ΠΏΠΎΠ·Π΄Π½Π΅Π΅.

ΠœΠ΅Ρ‚Π°Ρ„ΠΎΡ€Π°

НС всС опрСдСлСния Ρ…ΠΎΡ€ΠΎΡˆΠΈ ΠΈ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½ΡƒΠΆΠ΄Π°ΡŽΡ‚ΡΡ Π² Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌ объяснСнии, ΠΏΠΎΡ‚ΠΎΠΌΡƒ ΠΊ Ρ„ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎ Π²Π²Π΅Π΄Π΅Π½Π½ΠΎΠΉ Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΎΠ»ΠΎΠ³ΠΈΠΈ добавлю ΠΌΠ΅Ρ‚Π°Ρ„ΠΎΡ€Ρƒ ΠΎ ΠΏΡ€ΠΈΠ³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½ΠΈΠΈ Π·Π°Π²Ρ‚Ρ€Π°ΠΊΠ°. ΠŸΡ€ΠΈΠ³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ Π·Π°Π²Ρ‚Ρ€Π°ΠΊΠ° Π² этой ΠΌΠ΅Ρ‚Π°Ρ„ΠΎΡ€Π΅ β€” process.

Готовя Π·Π°Π²Ρ‚Ρ€Π°ΠΊ с ΡƒΡ‚Ρ€Π° я (CPU) ΠΏΡ€ΠΈΡ…ΠΎΠΆΡƒ Π½Π° ΠΊΡƒΡ…Π½ΡŽ (ΠšΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€). Π£ мСня 2 Ρ€ΡƒΠΊΠΈ (Cores). На ΠΊΡƒΡ…Π½Π΅ Π΅ΡΡ‚ΡŒ ряд устройств (IO): ΠΏΠ΅Ρ‡ΡŒ, Ρ‡Π°ΠΉΠ½ΠΈΠΊ, тостСр, Ρ…ΠΎΠ»ΠΎΠ΄ΠΈΠ»ΡŒΠ½ΠΈΠΊ. Π― Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽ Π³Π°Π·, ΡΡ‚Π°Π²Π»ΡŽ Π½Π° Π½Π΅Π³ΠΎ сковородку ΠΈ наливаю Ρ‚ΡƒΠ΄Π° масло, Π½Π΅ доТидаясь ΠΏΠΎΠΊΠ° ΠΎΠ½Π° разогрССтся (асинхронно, Non-Blocking-IO-Wait), я Π΄ΠΎΡΡ‚Π°ΡŽ ΠΈΠ· Ρ…ΠΎΠ»ΠΎΠ΄ΠΈΠ»ΡŒΠ½ΠΈΠΊΠ° яйца ΠΈ Ρ€Π°Π·Π±ΠΈΠ²Π°ΡŽ ΠΈΡ… Π² Ρ‚Π°Ρ€Π΅Π»ΠΊΡƒ, послС Ρ‡Π΅Π³ΠΎ взбиваю ΠΎΠ΄Π½ΠΎΠΉ Ρ€ΡƒΠΊΠΎΠΉ (Thread#1), Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ (Thread#2) ΠΏΡ€ΠΈΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽ Ρ‚Π°Ρ€Π΅Π»ΠΊΡƒ (Shared Resource). БСйчас Π±Ρ‹ Π΅Ρ‰Π΅ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Ρ‡Π°ΠΉΠ½ΠΈΠΊ, Π½ΠΎ Ρ€ΡƒΠΊ Π½Π΅ Ρ…Π²Π°Ρ‚Π°Π΅Ρ‚ (Thread Starvation) Π—Π° это врСмя разогрСваСтся сковородка (ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°) ΠΊΡƒΠ΄Π° я Π²Ρ‹Π»ΠΈΠ²Π°ΡŽ Ρ‚ΠΎ Ρ‡Ρ‚ΠΎ Π²Π·Π±ΠΈΠ». Π― Π΄ΠΎΡ‚ΡΠ³ΠΈΠ²Π°ΡŽΡΡŒ Π΄ΠΎ Ρ‡Π°ΠΉΠ½ΠΈΠΊΠ° ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽ Π΅Π³ΠΎ ΠΈ Ρ‚ΡƒΠΏΠΎ ΡΠΌΠΎΡ‚Ρ€ΡŽ ΠΊΠ°ΠΊ Π²ΠΎΠ΄Π° Π² Π½Π΅ΠΌ Π·Π°ΠΊΠΈΠΏΠ°Π΅Ρ‚ (Blocking-IO-Wait), хотя ΠΌΠΎΠ³ Π±Ρ‹ Π·Π° это врСмя Π²Ρ‹ΠΌΡ‹Ρ‚ΡŒ Ρ‚Π°Ρ€Π΅Π»ΠΊΡƒ, Π³Π΄Π΅ Π²Π·Π±ΠΈΠ²Π°Π» ΠΎΠΌΠ»Π΅Ρ‚.

Π― Π³ΠΎΡ‚ΠΎΠ²ΠΈΠ» ΠΎΠΌΠ»Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ всСго 2 Ρ€ΡƒΠΊΠΈ, Π΄Π° большС Ρƒ мСня ΠΈ Π½Π΅Ρ‚, Π½ΠΎ ΠΏΡ€ΠΈ этом Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ взбивания ΠΎΠΌΠ»Π΅Ρ‚Π° происходило сразу 3 ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: Π²Π·Π±ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΎΠΌΠ»Π΅Ρ‚Π°, ΠΏΡ€ΠΈΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Ρ‚Π°Ρ€Π΅Π»ΠΊΠΈ, Ρ€Π°Π·ΠΎΠ³Ρ€Π΅Π²Π°Π½ΠΈΠ΅ сковородки.CPU β€” являСтся самой быстрой Ρ‡Π°ΡΡ‚ΡŒΡŽ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°, IO это Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Ρ‡Π°Ρ‰Π΅ всСго Ρ‚ΠΎΡ€ΠΌΠΎΠ·ΠΈΡ‚, ΠΏΠΎΡ‚ΠΎΠΌΡƒ часто эффСктивным Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠΌ являСтся Π·Π°Π½ΡΡ‚ΡŒ Ρ‡Π΅ΠΌ-Ρ‚ΠΎ CPU ΠΏΠΎΠΊΠ° ΠΈΠ΄Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΡ‚ IO.

ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ ΠΌΠ΅Ρ‚Π°Ρ„ΠΎΡ€Ρƒ:

  • Если Π±Ρ‹ Π² процСссС Π³ΠΎΡ‚ΠΎΠ²ΠΊΠΈ ΠΎΠΌΠ»Π΅Ρ‚Π°, я Π±Ρ‹ Π΅Ρ‰Π΅ ΠΈ пытался ΠΏΠ΅Ρ€Π΅ΠΎΠ΄Π΅Ρ‚ΡŒΡΡ это Π±Ρ‹Π» Π±Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ многозадачности. Π’Π°ΠΆΠ½Ρ‹ΠΉ нюанс: Ρƒ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€ΠΎΠ² с этим ΠΊΡƒΠ΄Π° Π»ΡƒΡ‡ΡˆΠ΅ Ρ‡Π΅ΠΌ Ρƒ людСй.
  • ΠšΡƒΡ…Π½Ρ с нСсколькими ΠΏΠΎΠ²Π°Ρ€Π°ΠΌΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π² рСсторанС β€” многоядСрный ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€.
  • ΠœΠ½ΠΎΠΆΠ΅ΡΡ‚Π²ΠΎ рСсторанов Π½Π° Ρ„ΡƒΠ΄ΠΊΠΎΡ€Ρ‚Π΅ Π² Ρ‚ΠΎΡ€Π³ΠΎΠ²ΠΎΠΌ Ρ†Π΅Π½Ρ‚Ρ€Π΅ β€” Π΄Π°Ρ‚Π°Ρ†Π΅Π½Ρ‚Ρ€

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ .NET

Π’ Ρ€Π°Π±ΠΎΡ‚Π΅ с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ, ΠΊΠ°ΠΊ ΠΈ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΌ, .NET Ρ…ΠΎΡ€ΠΎΡˆ. Π‘ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π½ΠΎΠ²ΠΎΠΉ вСрсиСй ΠΎΠ½ прСдставляСт всС большС Π½ΠΎΠ²Ρ‹Ρ… инструмСнтов для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π½ΠΈΠΌΠΈ, Π½ΠΎΠ²Ρ‹Π΅ слои абстракции Π½Π°Π΄ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ ОБ. Π’ Ρ€Π°Π±ΠΎΡ‚Π΅ с построСниСм абстракций Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ использовании высокоуровнСвой абстракции, спустится Π½Π° ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ нСсколько ΡƒΡ€ΠΎΠ²Π½Π΅ΠΉ Π½ΠΈΠΆΠ΅. Π§Π°Ρ‰Π΅ всСго Π² этом Π½Π΅Ρ‚ нСобходимости, Π±ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ³ΠΎ это ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ для выстрСла сСбС Π² Π½ΠΎΠ³Ρƒ ΠΈΠ· Π΄Ρ€ΠΎΠ±ΠΎΠ²ΠΈΠΊΠ°, Π½ΠΎ ΠΈΠ½ΠΎΠ³Π΄Π°, Π² Ρ€Π΅Π΄ΠΊΠΈΡ… случаях, это ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ СдинствСнным способом Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, Π½Π΅ Ρ€Π΅ΡˆΠ°ΡŽΡ‰ΡƒΡŽ Π½Π° Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅ абстракции.

Под инструмСнтами я имСю Π²Π²ΠΈΠ΄Ρƒ ΠΊΠ°ΠΊ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Π΅ интСрфСйсы (API) прСдоставляСмыС Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠΌ ΠΈ сторонними ΠΏΠ°ΠΊΠ΅Ρ‚Π°ΠΌΠΈ, Ρ‚Π°ΠΊ ΠΈ Ρ†Π΅Π»Ρ‹ΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΡƒΠΏΡ€ΠΎΡ‰Π°ΡŽΡ‰ΠΈΠΉ поиск ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ связанных с ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½Ρ‹ΠΌ ΠΊΠΎΠ΄ΠΎΠΌ.

Запуск ΠΏΠΎΡ‚ΠΎΠΊΠ°

Класс Thread, самый Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ Π² .NET для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ. Π’ конструктор ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π΄Π²ΡƒΡ… Π΄Π΅Π»Π΅Π³Π°Ρ‚ΠΎΠ²:

  • ThreadStart β€” Π‘Π΅Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ²
  • ParametrizedThreadStart β€” с ΠΎΠ΄Π½ΠΈΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ Ρ‚ΠΈΠΏΠ° object.

Π”Π΅Π»Π΅Π³Π°Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ Π²ΠΎ вновь созданном ΠΏΠΎΡ‚ΠΎΠΊΠ΅ послС Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Start, Ссли Π² конструктор Π±Ρ‹Π» ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ Π΄Π΅Π»Π΅Π³Π°Ρ‚ Ρ‚ΠΈΠΏΠ° ParametrizedThreadStart, Ρ‚ΠΎ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ Start Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚. Π­Ρ‚ΠΎΡ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Π½ΡƒΠΆΠ΅Π½ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ любой локальной ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ Π² ΠΏΠΎΡ‚ΠΎΠΊ. Π‘Ρ‚ΠΎΠΈΡ‚ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ Ρ‡Ρ‚ΠΎ созданиС ΠΏΠΎΡ‚ΠΎΠΊΠ° это дорогостоящая опСрация, Π° сам ΠΏΠΎΡ‚ΠΎΠΊ это тяТСлый ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ происходит Π²Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠ΅ 1ΠœΠ‘ памяти Π½Π° стСк, ΠΈ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ взаимодСйствия с API ОБ.

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

Класс ThreadPool прСдставляСт ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΡŽ ΠΏΡƒΠ»Π°. Π’ .NET ΠΏΡƒΠ» ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² являСтся ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€Π½ΠΎΠ³ΠΎ искусства ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΈΠ· Microsoft Π²Π»ΠΎΠΆΠΈΠ»ΠΈ мноТСство усилий, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ Ρ€Π°Π±ΠΎΡ‚Π°Π» ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎ Π² самых Ρ€Π°Π·Π½Ρ‹Ρ… сцСнариях.

ΠžΠ±Ρ‰Π°Ρ концСпция:

Π‘ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° старта ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π² Ρ„ΠΎΠ½Π΅ создаСт нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΏΡ€ΠΎ запас ΠΈ прСдоставляСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π±Ρ€Π°Ρ‚ΡŒ ΠΈΡ… Π² пользованиС. Если ΠΏΠΎΡ‚ΠΎΠΊΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ часто ΠΈ Π² большом количСствС, Ρ‚ΠΎ ΠΏΡƒΠ» Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€ΠΈΡ‚ΡŒ ΠΏΠΎΡ‚Ρ€Π΅Π±Π½ΠΎΡΡ‚ΡŒ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π³ΠΎ ΠΊΠΎΠ΄Π°. Когда Π² ΠΏΡƒΠ»Π΅ Π² Π½ΡƒΠΆΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Π½Π΅ оказываСтся свободных ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΠ½ ΠΈΠ»ΠΈ доТдСтся Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², Π»ΠΈΠ±ΠΎ создаст Π½ΠΎΠ²Ρ‹ΠΉ. Из этого слСдуСт, Ρ‡Ρ‚ΠΎ ΠΏΡƒΠ» ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для Π½Π΅ΠΊΠΈΡ… ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΡ… дСйствий ΠΈ ΠΏΠ»ΠΎΡ…ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚, для ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΠΈΡ… ΠΊΠ°ΠΊ слуТбы Π½Π° протяТСнии всСй Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ.

Для использования ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈΠ· ΠΏΡƒΠ»Π°, Π΅ΡΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ QueueUserWorkItem, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π΄Π΅Π»Π΅Π³Π°Ρ‚ Ρ‚ΠΈΠΏΠ° WaitCallback, Ρ‡Ρ‚ΠΎ ΠΏΠΎ сигнатурС совпадаСт с ParametrizedThreadStart, Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹ΠΉ Π² Π½Π΅Π³ΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ выполняСт Ρ‚ΡƒΠΆΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ.

ThreadPool.QueueUserWorkItem(...);

МСнСС извСстный ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΡƒΠ»Π° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² RegisterWaitForSingleObject слуТит для ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΡ… IO ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Π”Π΅Π»Π΅Π³Π°Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ Π² этот ΠΌΠ΅Ρ‚ΠΎΠ΄ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ Ρ‚ΠΎΠ³Π΄Π°, ΠΊΠΎΠ³Π΄Π° WaitHandle ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ Π±ΡƒΠ΄Π΅Ρ‚ β€œΠΎΡ‚ΠΏΡƒΡ‰Π΅Π½β€(Released).

ThreadPool.RegisterWaitForSingleObject(...)

Π’ .NET Π΅ΡΡ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Ρ‹ΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ ΠΈ отличаСтся ΠΎΠ½ ΠΎΡ‚ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠ² WinForms/WPF Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅ взятом ΠΈΠ· ΠΏΡƒΠ»Π°.

System.Threading.Timer

Π’Π°ΠΊ ΠΆΠ΅ Π΅ΡΡ‚ΡŒ довольно экзотичСский способ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π΄Π΅Π»Π΅Π³Π°Ρ‚ Π½Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π² ΠΏΠΎΡ‚ΠΎΠΊ ΠΈΠ· ΠΏΡƒΠ»Π° β€” ΠΌΠ΅Ρ‚ΠΎΠ΄ BeginInvoke.

DelegateInstance.BeginInvoke

Π₯ΠΎΡ‡Ρƒ Π΅Ρ‰Π΅ вскользь остановится Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΊ Π²Ρ‹Π·ΠΎΠ²Ρƒ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ сводится ΠΌΠ½ΠΎΠ³ΠΈΠ΅ ΠΈΠ· Π²Ρ‹ΡˆΠ΅ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² β€” CreateThread ΠΈΠ· Kernel32.dll Win32 API. БущСствуСт способ, благодаря ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡƒ extern ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ. Π― Π²ΠΈΠ΄Π΅Π» Ρ‚Π°ΠΊΠΎΠΉ Π²Ρ‹Π·ΠΎΠ² лишь ΠΎΠ΄Π½Π°ΠΆΠ΄Ρ‹ Π² ΠΆΡƒΡ‚Ρ‡Π°ΠΉΡˆΠ΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ legacy ΠΊΠΎΠ΄Π°, Π° мотивация Π°Π²Ρ‚ΠΎΡ€Π° сдСлавшСго ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊ всС Π΅Ρ‰Π΅ остаСтся для мСня Π·Π°Π³Π°Π΄ΠΊΠΎΠΉ.

Kernel32.dll CreateThread

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€ ΠΈ ΠΎΡ‚Π»Π°Π΄ΠΊΠ° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²

Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹Π΅ Π²Π°ΠΌΠΈ Π»ΠΈΡ‡Π½ΠΎ, всСми трСтисторонними ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ ΠΈ ΠΏΡƒΠ»ΠΎΠΌ .NET ΠΏΠΎΡ‚ΠΎΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π² ΠΎΠΊΠ½Π΅ Threads Visual Studio. Π­Ρ‚ΠΎ ΠΎΠΊΠ½ΠΎ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ… лишь, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ находится ΠΏΠΎΠ΄ ΠΎΡ‚Π»Π°Π΄ΠΊΠΎΠΉ ΠΈ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ останова (Break mode). Π—Π΄Π΅ΡΡŒ ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ стСк ΠΈΠΌΠ΅Π½Π° ΠΈ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚Ρ‹ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΎΡ‚Π»Π°Π΄ΠΊΡƒ Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ. Бвойством Priority класса Thread ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ OC ΠΈ CLR Π±ΡƒΠ΄ΡƒΡ‚ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ ΠΊΠ°ΠΊ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ ΠΏΡ€ΠΈ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠΈ процСссорного Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ.

.NET: Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ. Π§Π°ΡΡ‚ΡŒ 1

Task Parallel Library

Task Parallel Library (TPL) появился Π² .NET 4.0. БСйчас это стандарт ΠΈ основной инструмСнт для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ. Π›ΡŽΠ±ΠΎΠΉ ΠΊΠΎΠ΄ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠΉ Π±ΠΎΠ»Π΅Π΅ старыС ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ считаСтся legacy. Основной Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ΠΉ TPL являСтся класс Task ΠΈΠ· пространства ΠΈΠΌΠ΅Π½ System.Threading.Tasks. Task прСдставляСт собой Π°Π±ΡΡ‚Ρ€Π°ΠΊΡ†ΠΈΡŽ Π½Π°Π΄ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ. Π‘ Π½ΠΎΠ²ΠΎΠΉ вСрсиСй языка C# ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ изящный способ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Task`Π°ΠΌΠΈ β€” ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ async/await. Π­Ρ‚ΠΈ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ»ΠΈ ΠΏΠΈΡΠ°Ρ‚ΡŒ асинхронный ΠΊΠΎΠ΄ Ρ‚Π°ΠΊ, ΠΊΠ°ΠΊ Ссли Π±Ρ‹ ΠΎΠ½ Π±Ρ‹Π» простым ΠΈ синхронным, это Π΄Π°Π»ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π΄Π°ΠΆΠ΅ людям слабо ΠΏΠΎΠ½ΠΈΠΌΠ°ΡŽΡ‰ΠΈΠΌ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΡŽΡŽ ΠΊΡƒΡ…Π½ΡŽ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΏΠΈΡΠ°Ρ‚ΡŒ прилоТСния ΠΈΡ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠ΅, прилоТСния Π½Π΅ Π·Π°Π²ΠΈΡΠ°ΡŽΡ‰ΠΈΠ΅ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π΄ΠΎΠ»Π³ΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. ИспользованиС async/await Ρ‚Π΅ΠΌΠ° для ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… статСй, Π½ΠΎ я ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΡŽ Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… прСдлоТСниях ΡƒΠ»ΠΎΠΆΠΈΡ‚ΡŒ ΡΡƒΡ‚ΡŒ:

  • async это ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰Π΅Π³ΠΎ Task ΠΈΠ»ΠΈ void
  • Π° await ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ оТидания Task`Π°.

Π•Ρ‰Π΅ Ρ€Π°Π·: ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ await, Π² ΠΎΠ±Ρ‰Π΅ΠΌ случаС (Π΅ΡΡ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ), отпустит Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ выполнСния дальшС, Π° ΠΊΠΎΠ³Π΄Π° Task Π·Π°ΠΊΠΎΠ½Ρ‡ΠΈΡ‚ своС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅, Π° ΠΏΠΎΡ‚ΠΎΠΊ (Π½Π° самом Π΄Π΅Π»Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π΅Π΅ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ контСкст, Π½ΠΎ ΠΎΠ± этом ΠΏΠΎΠ·Π΄Π½Π΅Π΅) Π±ΡƒΠ΄Π΅Ρ‚ свободСн ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° дальшС. Π’Π½ΡƒΡ‚Ρ€ΠΈ .NET этот ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΊΠ°ΠΊ ΠΈ yield return, ΠΊΠΎΠ³Π΄Π° написанный ΠΌΠ΅Ρ‚ΠΎΠ΄ прСвращаСтся Π² Ρ†Π΅Π»Ρ‹ΠΉ класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ являСтся машиной состояний ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ кусками Π² зависимости ΠΎΡ‚ этих состояний. ΠšΠΎΠΌΡƒ интСрСсно ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ любой нСслоТный ΠΊΠΎΠ΄ с использованиСм asynс/await, ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ сборку с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ JetBrains dotPeek с Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹ΠΌ Compiler Generated Code.

Рассмотрим Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Ρ‹ запуска ΠΈ использования Task’а. На ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΊΠΎΠ΄Π° Π½ΠΈΠΆΠ΅, ΠΌΡ‹ создаСм Π½ΠΎΠ²Ρ‹ΠΉ таск, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚ Π½ΠΈΡ‡Π΅Π³ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠ³ΠΎ (Thread.Sleep(10000)), Π½ΠΎ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ ΠΆΠΈΠ·Π½ΠΈ это Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ нСкая слоТная Π·Π°Π΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ 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
}

Task создаСтся с рядом ΠΎΠΏΡ†ΠΈΠΉ:

  • LongRunning β€” подсказка ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π·Π°Π΄Π°Ρ‡Π° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° быстро, Π° Π·Π½Π°Ρ‡ΠΈΡ‚, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, стоит ΠΏΠΎΠ΄ΡƒΠΌΠ°Ρ‚ΡŒ Π½Π°Π΄ Ρ‚Π΅ΠΌ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π±Ρ€Π°Ρ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊ ΠΈΠ· ΠΏΡƒΠ»Π°, Π° ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΠ΄ эту Task’у Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π½Π°Π²Ρ€Π΅Π΄ΠΈΡ‚ΡŒ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹ΠΌ.
  • AttachedToParent β€” Task’и ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒΡΡ Π² ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΠΈ. Если Π±Ρ‹Π»Π° использована эта опция, Ρ‚ΠΎ Task ΠΌΠΎΠΆΠ΅Ρ‚ находится Π² состоянии, ΠΊΠΎΠ³Π΄Π° сам ΠΎΠ½ выполнился ΠΈ доТидаСтся выполнСния Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ….
  • PreferFairness β€” ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ…ΠΎΡ€ΠΎΡˆΠΎ Π±Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Task’и ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹Π΅ Π½Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ€Π°Π½ΡŒΡˆΠ΅ ΠΏΠ΅Ρ€Π΅Π΄ Ρ‚Π΅ΠΌΠΈ, Ρ‡Ρ‚ΠΎ Π±Ρ‹Π»ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ ΠΏΠΎΠ·ΠΆΠ΅. Но это всСго лишь рСкомСндация ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π½Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½.

Π’Ρ‚ΠΎΡ€Ρ‹ΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ CancellationToken. Для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ послС Π΅Π΅ запуска выполняСмый ΠΊΠΎΠ΄ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π½Π°ΠΏΠΎΠ»Π½Π΅Π½ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°ΠΌΠΈ состояния CancellationToken. Если ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ Π½Π΅Ρ‚, Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ Cancel Π²Ρ‹Π·Π²Π°Π½Π½Ρ‹ΠΉ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ CancellationTokenSource смоТСт ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Task’а лишь Π΄ΠΎ Π΅Π³ΠΎ запуска.

ПослСдним ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ scheduler Ρ‚ΠΈΠΏΠ° TaskScheduler. Π­Ρ‚ΠΎΡ‚ класс ΠΈ Π΅Π³ΠΎ наслСдники ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Ρ‹ для управлСния стратСгиями распрСдСлСния Task’ов ΠΏΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ, ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Task Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ Π½Π° случайном ΠΏΠΎΡ‚ΠΎΠΊΠ΅ ΠΈΠ· ΠΏΡƒΠ»Π°.

К созданному Task’у ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ await, Π° Π·Π½Π°Ρ‡ΠΈΡ‚ ΠΊΠΎΠ΄ написанный послС Π½Π΅Π³ΠΎ, Ссли Ρ‚Π°ΠΊΠΎΠΉ Π΅ΡΡ‚ΡŒ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ контСкстС (часто это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Ρ‡Ρ‚ΠΎ Π½Π° Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ΅), Ρ‡Ρ‚ΠΎ ΠΈ ΠΊΠΎΠ΄ Π΄ΠΎ await.

ΠœΠ΅Ρ‚ΠΎΠ΄ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½ ΠΊΠ°ΠΊ async void, это Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ Π² Π½Π΅ΠΌ допустимо использованиС ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° await, Π½ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ Π½Π΅ смоТСт Π΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒΡΡ выполнСния. Если такая Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ°, Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Task. ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Π½Ρ‹Π΅ async void Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡ‚ΡΡ довольно часто: ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ это ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ событий ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΠΎ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΈ Π·Π°Π±Ρ‹Ρ‚ΡŒ (fire and forget). Если Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π°Ρ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒΡΡ окончания выполнСния, Π½ΠΎ ΠΈ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Ρ‚ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Task.

На Task’С Ρ‡Ρ‚ΠΎ Π²Π΅Ρ€Π½ΡƒΠ» ΠΌΠ΅Ρ‚ΠΎΠ΄ StartNew, Π²ΠΏΡ€ΠΎΡ‡Π΅ΠΌ ΠΊΠ°ΠΊ ΠΈ Π½Π° любом Π΄Ρ€ΡƒΠ³ΠΎΠΌ, ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ ConfigureAwait с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ false, Ρ‚ΠΎΠ³Π΄Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ послС await продолТится Π½Π΅ Π½Π° Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½Π½ΠΎΠΌ контСкстС, Π° Π½Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎΠΌ. Π­Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ всСгда, ΠΊΠΎΠ³Π΄Π° для ΠΊΠΎΠ΄Π° послС await Π½Π΅ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΈΠ°Π»Π΅Π½ контСкст выполнСния. Π’Π°ΠΊΠΆΠ΅ это являСтся Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠ΅ΠΉ ΠΎΡ‚ MS ΠΏΡ€ΠΈ написании ΠΊΠΎΠ΄Π°, Ρ‡Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡΡ‚Π°Π²Π»ΡΡ‚ΡŒΡΡ ΡƒΠΏΠ°ΠΊΠΎΠ²Π°Π½Π½ΠΎΠΌ Π² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ Π²ΠΈΠ΄Π΅.

Π”Π°Π²Π°ΠΉΡ‚Π΅ Π΅Ρ‰Π΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ остановимся Π½Π° Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒΡΡ окончания выполнСния Task’и. НиТС ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ΄Π°, с коммСнтариями, ΠΊΠΎΠ³Π΄Π° ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ сдСлано условно Ρ…ΠΎΡ€ΠΎΡˆΠΎ ΠΈ ΠΊΠΎΠ³Π΄Π° условно ΠΏΠ»ΠΎΡ…ΠΎ.

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
}

Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ доТидаСмся выполнСния Task’и Π½Π΅ блокируя Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, ΠΊ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° вСрнСмся лишь ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ ΡƒΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚, Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ прСдоставлСн сСбС.

Π’ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π΅ ΠΌΡ‹ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€ ΠΏΠΎΠΊΠ° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ подсчитан Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°. Π­Ρ‚ΠΎ ΠΏΠ»ΠΎΡ…ΠΎ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ заняли ΠΏΠΎΡ‚ΠΎΠΊ, ΡΡ‚ΠΎΠ»ΡŒ Ρ†Π΅Π½Π½Ρ‹ΠΉ рСсурс ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, простым Π±Π΅Π·Π΄Π΅Π»ΠΈΠ΅ΠΌ, Π½ΠΎ Π΅Ρ‰Π΅ ΠΈ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Ссли Π² ΠΊΠΎΠ΄Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Π΅ΡΡ‚ΡŒ await, Π° контСкст синхронизации ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ Π² Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ послС await, Ρ‚ΠΎ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ deadlock: Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΆΠ΄Π΅Ρ‚ ΠΏΠΎΠΊΠ° Π±ΡƒΠ΄Π΅Ρ‚ вычислСн Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ асинхронного ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, асинхронный ΠΌΠ΅Ρ‚ΠΎΠ΄ Ρ‚Ρ‰Π΅Ρ‚Π½ΠΎ пытаСтся ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ своС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π² Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅.

Π•Ρ‰Π΅ ΠΎΠ΄Π½ΠΈΠΌ нСдостатком Ρ‚Π°ΠΊΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° являСтся услоТнСнная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок. Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ошибки Π² асинхронном ΠΊΠΎΠ΄Π΅ ΠΏΡ€ΠΈ использовании async/await ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΎΡ‡Π΅Π½ΡŒ Π»Π΅Π³ΠΊΠΎ β€” ΠΎΠ½ΠΈ Π²Π΅Π΄ΡƒΡ‚ сСбя Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΊΠ°ΠΊ Ссли Π±Ρ‹ ΠΊΠΎΠ΄ Π±Ρ‹Π» синхронным. Π’ Ρ‚ΠΎ врСмя, ΠΊΠ°ΠΊ Ссли ΠΌΡ‹ примСняСм экзорцизм синхронноС ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ ΠΊ Task’e ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ оборачиваСтся Π² AggregateException, Ρ‚.ΠΎ. Для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ придСтся ΠΈΡΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏ InnerException ΠΈ самому ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ if Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ catch Π±Π»ΠΎΠΊΠ° ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ catch when, вмСсто Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΈΠ²Ρ‹Ρ‡Π½ΠΎΠΉ Π² C# ΠΌΠΈΡ€Π΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ catch Π±Π»ΠΎΠΊΠΎΠ².

Π’Ρ€Π΅Ρ‚ΠΈΠΉ ΠΈ послСдний ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½Ρ‹ ΠΏΠ»ΠΎΡ…ΠΈΠΌΠΈ ΠΏΠΎ Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ ΠΈ содСрТат всС Ρ‚Π΅ ΠΆΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹.

ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ WhenAny ΠΈ WhenAll ΠΊΡ€Π°ΠΉΠ½Π΅ ΡƒΠ΄ΠΎΠ±Π½Ρ‹ Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ Π³Ρ€ΡƒΠΏΠΏΡ‹ Task’ов, ΠΎΠ½ΠΈ ΠΎΠ±ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°ΡŽΡ‚ Π³Ρ€ΡƒΠΏΠΏΡƒ Task’ов Π² ΠΎΠ΄ΠΈΠ½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ сработаСт Π»ΠΈΠ±ΠΎ ΠΏΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ ΡΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π½ΠΈΡŽ Task’а ΠΈΠ· Π³Ρ€ΡƒΠΏΠΏΡ‹, Π»ΠΈΠ±ΠΎ ΠΊΠΎΠ³Π΄Π° своС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠΎΠ½Ρ‡Π°Ρ‚ всС.

ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²

По Ρ€Π°Π·Π½Ρ‹ΠΌ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ появится Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊ послС Π΅Π³ΠΎ старта. Для этого сущСствуСт ряд способов. Π£ класса Thread Π΅ΡΡ‚ΡŒ Π΄Π²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° с подходящими названиями β€” это Abort ΠΈ Interrupt. ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ ΠΊΡ€Π°ΠΉΠ½Π΅ Π½Π΅ рСкомСндуСтся ΠΊ использованию, Ρ‚.ΠΊ. послС Π΅Π³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° Π² любой случайный ΠΌΠΎΠΌΠ΅Π½Ρ‚, Π² процСссС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ любой инструкции, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π±Ρ€ΠΎΡˆΠ΅Π½ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ThreadAbortedException. Π’Ρ‹ вСдь Π½Π΅ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚Π΅ Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π²Ρ‹Π»Π΅Ρ‚ΠΈΡ‚ ΠΏΡ€ΠΈ ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚Π΅ ΠΊΠ°ΠΊΠΎΠΉ-Π»ΠΈΠ±ΠΎ цСлочислСнной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π²Π΅Ρ€Π½ΠΎ? А ΠΏΡ€ΠΈ использовании этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π° это Π²ΠΏΠΎΠ»Π½Π΅ Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ ситуация. Π’ случаС нСобходимости Π·Π°ΠΏΡ€Π΅Ρ‚ΠΈΡ‚ΡŒ CLR Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ участкС ΠΊΠΎΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π΅Π³ΠΎ Π² Π²Ρ‹Π·ΠΎΠ²Ρ‹ Thread.BeginCriticalRegion, Thread.EndCriticalRegion. Π’Π°ΠΊΠΈΠΌΠΈ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ оборачиваСтся любой ΠΊΠΎΠ΄ написанный Π² finally Π±Π»ΠΎΠΊΠ΅. По этой ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Π² Π½Π΅Π΄Ρ€Π°Ρ… ΠΊΠΎΠ΄Π° Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π±Π»ΠΎΠΊΠΈ с пустым try, Π½ΠΎ Π½Π΅ пустым finally. Microsoft Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ этот ΠΌΠ΅Ρ‚ΠΎΠ΄, Ρ‡Ρ‚ΠΎ Π½Π΅ Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ»ΠΈ Π΅Π³ΠΎ Π² .net core.

ΠœΠ΅Ρ‚ΠΎΠ΄ Interrupt Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π±ΠΎΠ»Π΅Π΅ прСдсказуСмо. Он ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€Π΅Ρ€Π²Π°Ρ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ ThreadInterruptedException Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚Π΅ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρ‹, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΡ‚ΠΎΠΊ находится Π² состоянии оТидания. Π’ Ρ‚Π°ΠΊΠΎΠ΅ состояниС ΠΎΠ½ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ подвисая Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ WaitHandle, lock ΠΈΠ»ΠΈ послС Π²Ρ‹Π·ΠΎΠ²Π° Thread.Sleep.

Оба описанных Π²Ρ‹ΡˆΠ΅ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°, ΠΏΠ»ΠΎΡ…ΠΈ своСй Π½Π΅ΠΏΡ€Π΅Π΄ΡΠΊΠ°Π·ΡƒΠ΅ΠΌΠΎΡΡ‚ΡŒΡŽ. Π’Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ являСтся использованиС структуры CancellationToken ΠΈ класса CancellationTokenSource. Π‘ΡƒΡ‚ΡŒ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ: создаСтся экзСмпляр класса CancellationTokenSource ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎΡ‚ ΠΊΡ‚ΠΎ ΠΈΠΌ Π²Π»Π°Π΄Π΅Π΅Ρ‚, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π²Ρ‹Π·Π²Π°Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ Cancel. Π’ саму ΠΆΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ пСрСдаСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ лишь CancellationToken. Π’Π»Π°Π΄Π΅Π»ΡŒΡ†Ρ‹ CancellationToken Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ сами ΠΎΡ‚ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Π° ΠΌΠΎΠ³ΡƒΡ‚ лишь ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π½Π΅ Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°. Для этого Π΅ΡΡ‚ΡŒ Π±ΡƒΠ»Π΅Π²ΠΎ свойство IsCancellationRequested ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ ThrowIfCancelRequested. ПослСдний сгСнСрируСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ TaskCancelledException Ссли Π½Π° ΠΏΠ°Ρ€ΠΎΠ΄ΠΈΠ²ΡˆΠ΅ΠΌ CancellationToken экзСмплярС CancellationTokenSource Π±Ρ‹Π» Π²Ρ‹Π·Π²Π°Π½ ΠΌΠ΅Ρ‚ΠΎΠ΄ Cancel. И ΠΈΠΌΠ΅Π½Π½ΠΎ этот ΠΌΠ΅Ρ‚ΠΎΠ΄ я Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ. Π­Ρ‚ΠΎ Π»ΡƒΡ‡ΡˆΠ΅ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ контроля Π½Π°Π΄ Ρ‚Π΅ΠΌ Π² ΠΊΠ°ΠΊΠΈΠ΅ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρ‹ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ опСрация ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€Π΅Ρ€Π²Π°Π½Π°.

Π‘Π°ΠΌΡ‹ΠΌ ТСстоким Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠΌ остановки ΠΏΠΎΡ‚ΠΎΠΊΠ°, являСтся Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Win32 API TerminateThread. ПовСдСниС CLR послС Π²Ρ‹Π·ΠΎΠ²Π° этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ нСпрСдсказуСмым. На MSDN ΠΆΠ΅ ΠΏΡ€ΠΎ эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ написано ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅: β€œTerminateThread is a dangerous function that should only be used in the most extreme cases. β€œ

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ legacy-API Π² Task Based с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° FromAsync

Если Π²Π°ΠΌ ΠΏΠΎΡΡ‡Π°ΡΡ‚Π»ΠΈΠ²ΠΈΠ»ΠΎΡΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π½Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅, Ρ‡Ρ‚ΠΎ Π±Ρ‹Π» Π½Π°Ρ‡Π°Ρ‚ ΡƒΠΆΠ΅ послС Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ Task’и Π±Ρ‹Π»ΠΈ Π²Π²Π΅Π΄Π΅Π½Ρ‹ ΠΈ пСрСстали Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ‚ΠΈΡ…ΠΈΠΉ уТас Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², Ρ‚ΠΎ Π²Π°ΠΌ Π½Π΅ придСтся ΠΈΠΌΠ΅Ρ‚ΡŒ Π΄Π΅Π»ΠΎ с большим количСством старых API, ΠΊΠ°ΠΊ трСтисторонних, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΌΡƒΡ‡Π΅Π½Ρ‹Ρ… вашСй ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ Π² ΠΏΡ€ΠΎΡˆΠ»ΠΎΠΌ. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, ΠΊΠΎΠΌΠ°Π½Π΄Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ .NET Framework ΠΏΠΎΠ·Π°Π±ΠΎΡ‚ΠΈΠ»Π°ΡΡŒ ΠΎ нас, хотя Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Ρ†Π΅Π»ΡŒΡŽ Π±Ρ‹Π»Π° Π·Π°Π±ΠΎΡ‚Π° ΠΎ сСбС. Как Π±Ρ‹ Ρ‚ΠΎ Π½ΠΈ Π±Ρ‹Π»ΠΎ Π² .NET Π΅ΡΡ‚ΡŒ ряд инструмСнтов для Π±Π΅Π·Π±ΠΎΠ»Π΅Π·Π½Π΅Π½Π½ΠΎΠ³ΠΎ прСобразования ΠΊΠΎΠ΄Π° написанного Π² старых ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π°Ρ… асинхронного программирования Π² Π½ΠΎΠ²ΡƒΡŽ. Один ΠΈΠ· Π½ΠΈΡ… это ΠΌΠ΅Ρ‚ΠΎΠ΄ FromAsync Ρƒ TaskFactory. На ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΊΠΎΠ΄Π° Π½ΠΈΠΆΠ΅, я ΠΎΠ±ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°ΡŽ старыС асинхронныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ класса WebRequest Π² Task с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π°.

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

Π­Ρ‚ΠΎ лишь ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΈ Π΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠ΅ со встроСнными Ρ‚ΠΈΠΏΠ°ΠΌΠΈ Π²Π°ΠΌ вряд Π»ΠΈ придСтся, Π½ΠΎ любой старый ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ просто ΠΊΠΈΡˆΠΈΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ BeginDoSomething Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰ΠΈΠΌΠΈ IAsyncResult ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ EndDoSomething Π΅Π³ΠΎ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰ΠΈΠΌΠΈ.

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ legacy-API Π² Task Based с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ класса TaskCompletionSource

Π•Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ Π²Π°ΠΆΠ½Ρ‹ΠΉ для рассмотрСния инструмСнт, это класс TaskCompletionSource. По функциям, Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ ΠΈ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΎΠ½ Ρ‡Π΅ΠΌ-Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ RegisterWaitForSingleObject класса ThreadPool ΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ я писал Π²Ρ‹ΡˆΠ΅. Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ этого класса ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ ΠΈ ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΎΠ±ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°Ρ‚ΡŒ старыС асинхронныС API Π² Task’и.

Π’Ρ‹ скаТСтС, Ρ‡Ρ‚ΠΎ я ΡƒΠΆΠ΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΠ» ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ FromAsync класса TaskFactory ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π½ΠΎΠΌ для этих Ρ†Π΅Π»Π΅ΠΉ. Π—Π΄Π΅ΡΡŒ придСтся Π²ΡΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ всю ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ развития асинхронных ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π² .net Ρ‡Ρ‚ΠΎ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π» microsoft Π·Π° послСдниС 15 Π»Π΅Ρ‚: Π΄ΠΎ Task-Based Asynchronous Pattern (TAP) сущСствовали Asynchronous Programming Pattern (APP), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±Ρ‹Π» ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… BeginDoSomething Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰Π΅ΠΌ IAsyncResult ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… EndDoSomething Π΅Π³ΠΎ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰Π΅ΠΌ ΠΈ для legacy этих Π³ΠΎΠ΄ΠΎΠ² ΠΊΠ°ΠΊ Ρ€Π°Π· ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄ FromAsync, Π½ΠΎ со Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ, Π½Π° смСну Π΅ΠΌΡƒ ΠΏΡ€ΠΈΡˆΠ΅Π» Event Based Asynchronous Pattern (EAP), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π», Ρ‡Ρ‚ΠΎ ΠΏΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡŽ выполнСния асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ΠΎ событиС.

TaskCompletionSource ΠΊΠ°ΠΊ Ρ€Π°Π· ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΈ Π² Task’и legacy-API построСнных Π²ΠΎΠΊΡ€ΡƒΠ³ событийной ΠΌΠΎΠ΄Π΅Π»ΠΈ. Π‘ΡƒΡ‚ΡŒ Π΅Π³ΠΎ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ: Ρƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° этого класса Π΅ΡΡ‚ΡŒ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ΅ свойство Ρ‚ΠΈΠΏΠ° Task состояниСм ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ SetResult, SetException ΠΈ ΠΏΡ€. Класса TaskCompletionSource. Π’ мСстах ΠΆΠ΅ Π³Π΄Π΅ Π±Ρ‹Π» ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ await ΠΊ этому Task’у ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ ΠΈΠ»ΠΈ ΠΎΠ±Ρ€ΡƒΡˆΠ΅Π½ с ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ Π² зависимости ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊ TaskCompletionSource ΠΌΠ΅Ρ‚ΠΎΠ΄Π°. Если всС Π΅Ρ‰Π΅ Π½Π΅ понятно, Ρ‚ΠΎ Π΄Π°Π²Π°ΠΉΡ‚Π΅ посмотрим Π½Π° этот ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ΄Π°, Π³Π΄Π΅ Π½Π΅ΠΊΠΎΠ΅ староС API Π²Ρ€Π΅ΠΌΠ΅Π½ EAP заворачиваСтся Π² Task ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ TaskCompletionSource: ΠΏΡ€ΠΈ срабатывании события Task Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Π½ Π² состояниС Completed, Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠ²ΡˆΠΈΠΉ ΠΊ этому Task’у ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ await Π²ΠΎΠ·ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ своС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ result.

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

ΠžΠ±Π΅Ρ€Ρ‚ΠΊΠ° старых API это Π½Π΅ всС Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€Π½ΡƒΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ TaskCompletionSource. ИспользованиС этого класса ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΠ½ΡƒΡŽ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ проСктирования Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… API, Π½Π° Task’ах, Ρ‡Ρ‚ΠΎ Π½Π΅ Π·Π°Π½ΠΈΠΌΠ°ΡŽΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠΈ. А ΠΏΠΎΡ‚ΠΎΠΊ, ΠΊΠ°ΠΊ ΠΌΡ‹ ΠΏΠΎΠΌΠ½ΠΈΠΌ рСсурс Π΄ΠΎΡ€ΠΎΠ³ΠΎΠΉ ΠΈ количСство ΠΈΡ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΎ (Π² основном объСмом RAM). Π­Ρ‚ΠΎΠ³ΠΎ ограничСния Π»Π΅Π³ΠΊΠΎ Π΄ΠΎΡΡ‚ΠΈΡ‡ΡŒ разрабатывая, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π°Π³Ρ€ΡƒΠΆΠ΅Π½Π½ΠΎΠ΅ web-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ со слоТной бизнСс Π»ΠΎΠ³ΠΈΠΊΠΎΠΉ. Рассмотрим Ρ‚Π΅ возмоТности ΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… я Π³ΠΎΠ²ΠΎΡ€ΡŽ Π½Π° Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΎΠ³ΠΎ Ρ‚Ρ€ΡŽΠΊΠ° ΠΊΠ°ΠΊ Long-Polling.

Если ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎ ΡΡƒΡ‚ΡŒ Ρ‚Ρ€ΡŽΠΊΠ° Π²ΠΎΡ‚ Π² Ρ‡Π΅ΠΌ: Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ ΠΎΡ‚ API ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… событиях происходящих Π½Π° Π΅Π³ΠΎ сторонС, ΠΏΡ€ΠΈ этом API ΠΏΠΎ ΠΊΠ°ΠΊΠΈΠΌ-Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π°ΠΌ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠΎΠ±Ρ‰ΠΈΡ‚ΡŒ ΠΎ событии, Π° ΠΌΠΎΠΆΠ΅Ρ‚ лишь Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ состояниС. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚Π°ΠΊΠΈΡ… β€” всС API построСнныС ΠΏΠΎΠ²Π΅Ρ€Ρ… HTTP Π΄ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ WebSocket ΠΈΠ»ΠΈ ΠΏΡ€ΠΈ нСвозмоТности ΠΏΠΎ ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ эту Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΡŽ. ΠšΠ»ΠΈΠ΅Π½Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ Ρƒ HTTP сСрвСра. HTTP сСрвСр Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ сам ΡΠΏΡ€ΠΎΠ²ΠΎΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ с ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ. ΠŸΡ€ΠΎΡΡ‚Ρ‹ΠΌ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠΌ являСтся опрос сСрвСра ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρƒ, Π½ΠΎ это создаСт Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ Π½Π° сСрвСр ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ Π² срСднСм TimerInterval / 2. Для ΠΎΠ±Ρ…ΠΎΠ΄Π° этого Π±Ρ‹Π» ΠΈΠ·ΠΎΠ±Ρ€Π΅Ρ‚Π΅Π½ Ρ‚Ρ€ΡŽΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ²ΡˆΠΈΠΉ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Long Polling, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ ΠΎΡ‚Π²Π΅Ρ‚Π° ΠΎΡ‚ сСрвСра Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€ ΠΏΠΎΠΊΠ° Π½Π΅ истСчСт Timeout ΠΈΠ»ΠΈ Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ событиС. Если событиС ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ, Ρ‚ΠΎ ΠΎΠ½ΠΎ обрабатываСтся, Ссли Π½Π΅Ρ‚, Ρ‚ΠΎ запрос посылаСтся Π·Π°Π½ΠΎΠ²ΠΎ.

while(!eventOccures && !timeoutExceeded)  {

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

Но Ρ‚Π°ΠΊΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ сСбя уТасно, ΠΊΠ°ΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ число ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΡ… событиС вырастСт, Ρ‚.ΠΊ. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ‚Π°ΠΊΠΎΠΉ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ события Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ Ρ†Π΅Π»Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ. Π”Π° ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ Π² 1мс Π½Π° срабатывании события, Ρ‡Π°Ρ‰Π΅ всСго это Π½Π΅ сущСствСнно, Π½ΠΎ Π·Π°Ρ‡Π΅ΠΌ Π΄Π΅Π»Π°Ρ‚ΡŒ ПО Ρ…ΡƒΠΆΠ΅ Ρ‡Π΅ΠΌ ΠΎΠ½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ? Если ΠΆΠ΅ ΡƒΠ±Ρ€Π°Ρ‚ΡŒ Thread.Sleep(1), Ρ‚ΠΎ зазря Π·Π°Π³Ρ€ΡƒΠ·ΠΈΠΌ ΠΎΠ΄Π½ΠΎ ядро процСссора Π½Π° 100% Π² Ρ…ΠΎΠ»ΠΎΡΡ‚ΡƒΡŽ Π²Ρ€Π°Ρ‰Π°ΡΡΡŒ Π² бСсполСзном Ρ†ΠΈΠΊΠ»Π΅. Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ TaskCompletionSource ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π΅Π»Π°Ρ‚ΡŒ этот ΠΊΠΎΠ΄ ΠΈ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ всС ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π΅Π½Π½Ρ‹Π΅ Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹:

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

Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠ΄ Π½Π΅ являСтся production-ready, Π° лишь дСмонстрационным. Для использования Π² Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… случаях Π½ΡƒΠΆΠ½ΠΎ Π΅Ρ‰Π΅, ΠΊΠ°ΠΊ-ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ ΠΊΠΎΠ³Π΄Π° сообщСниС ΠΏΡ€ΠΈΡˆΠ»ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π΅Π³ΠΎ Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚: Π² Ρ‚Π°ΠΊΠΎΠΌ случаС ΠΌΠ΅Ρ‚ΠΎΠ΄ AsseptMessageAsync Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΡƒΠΆΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π½Ρ‹ΠΉ Task. Если ΠΆΠ΅ этот случай ΠΈ являСтся Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ частым, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ΄ΡƒΠΌΠ°Ρ‚ΡŒ ΠΈ ΠΎΠ± использовании ValueTask.

ΠŸΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ запроса Π½Π° сообщСниС ΠΌΡ‹ создаСм ΠΈ ΠΏΠΎΠΌΠ΅Ρ‰Π°Π΅ΠΌ Π² ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ TaskCompletionSource, Π° Π΄Π°Π»Π΅Π΅ ΠΆΠ΄Π΅ΠΌ Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π²Π΅Π΅: истСчСт Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π» Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈΠ»ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ сообщСниС.

ValueTask: Π·Π°Ρ‡Π΅ΠΌ ΠΈ ΠΊΠ°ΠΊ

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ async/await ΠΊΠ°ΠΊ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ yield return Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΠ· ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΌΠ°ΡˆΠΈΠ½Ρƒ состояний, Π° это созданиС Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Ρ‡Ρ‚ΠΎ ΠΏΠΎΡ‡Ρ‚ΠΈ всСгда Π½Π΅ Π²Π°ΠΆΠ½ΠΎ, Π½ΠΎ Π² Ρ€Π΅Π΄ΠΊΠΈΡ… случаях ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ. Π­Ρ‚ΠΈΠΌ случаСм ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌΡ‹ΠΉ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ часто, Ρ€Π΅Ρ‡ΡŒ ΠΎ дСсятках ΠΈ сотнях тысяч Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² Π² сСкунду. Если Ρ‚Π°ΠΊΠΎΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ написан Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎ Π² Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ случаСв ΠΎΠ½ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ обходя всС await ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, Ρ‚ΠΎ .NET прСдоставляСт инструмСнт Ρ‡Ρ‚ΠΎ Π±Ρ‹ это ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ β€” структура ValueTask. Π§Ρ‚ΠΎΠ±Ρ‹ стало понятно рассмотрим ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π΅Π³ΠΎ использования: Π΅ΡΡ‚ΡŒ кСш Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ Ρ…ΠΎΠ΄ΠΈΠΌ ΠΎΡ‡Π΅Π½ΡŒ часто. КакиС-Ρ‚ΠΎ значСния Π² Π½Π΅ΠΌ Π΅ΡΡ‚ΡŒ ΠΈ Ρ‚ΠΎΠ³Π΄Π° ΠΌΡ‹ ΠΈΡ… просто Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ, Ссли Π½Π΅Ρ‚, Ρ‚ΠΎ ΠΈΠ΄Π΅ΠΌ Π² ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹ΠΉ IO Π·Π° Π½ΠΈΠΌΠΈ. ПослСднСС хочСтся Π΄Π΅Π»Π°Ρ‚ΡŒ асинхронно, Π° Π·Π½Π°Ρ‡ΠΈΡ‚ вСсь ΠΌΠ΅Ρ‚ΠΎΠ΄ получаСтся асинхронным. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ написания ΠΌΠ΅Ρ‚ΠΎΠ΄Π° β€” ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ:

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

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

Из-Π·Π° ТСлания Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, ΠΈ Π»Π΅Π³ΠΊΠΎΠΉ боязни ΠΏΠΎ-ΠΏΠΎΠ²ΠΎΠ΄Ρƒ Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎ сгСнСрируСт Roslyn компилируя этот ΠΊΠΎΠ΄, ΠΌΠΎΠΆΠ½ΠΎ этот ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

public Task<string> GetById(int id) {

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

Π”Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΆΠ΅ ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠΌ Π² этом случаС Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ hot-path, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ значСния ΠΈΠ· словаря Π²ΠΎΠΎΠ±Ρ‰Π΅ Π±Π΅Π· Π»ΠΈΡˆΠ½ΠΈΡ… Π°Π»Π»ΠΎΠΊΠ°Ρ†ΠΈΠΉ ΠΈ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Π½Π° GC, Π² Ρ‚ΠΎ врСмя ΠΊΠΎΠ³Π΄Π° Π² Ρ‚Π΅Ρ… Ρ€Π΅Π΄ΠΊΠΈΡ… случаях, ΠΊΠΎΠ³Π΄Π° Π½Π°ΠΌ всС Ρ‚Π°ΠΊΠΈ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ΄Ρ‚ΠΈ Π² IO Π·Π° Π΄Π°Π½Π½Ρ‹ΠΌΠΈ всС останСтся плюс/минус ΠΏΠΎ старому:

public ValueTask<string> GetById(int id) {

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

Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ этот Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠ΄Π°: ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈΠΈ значСния Π² кСшС ΠΌΡ‹ создаСм структуру, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΆΠ΅ таск Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π²Π΅Ρ€Π½ΡƒΡ‚ Π² Π·Π½Π°Ρ‡ΠΈΠΌΡ‹ΠΉ. Π’Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌΡƒ ΠΊΠΎΠ΄Ρƒ всС Ρ€Π°Π²Π½ΠΎ ΠΏΠΎ ΠΊΠ°ΠΊΠΎΠΌΡƒ ΠΏΡƒΡ‚ΠΈ выполнялся этот ΠΊΠΎΠ΄: ValueTask с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния синтаксиса C# Π±ΡƒΠ΄Π΅Ρ‚ вСсти сСбя Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΊΠ°ΠΊ ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ Task Π² этом случаС.

TaskScheduler’ы: ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ стратСгиями запуска Task’ов

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ API, Ρ‡Ρ‚ΠΎ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ это класс TaskScheduler ΠΈ Π΅Π³ΠΎ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹Π΅. Π― ΡƒΠΆΠ΅ ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π» Π²Ρ‹ΡˆΠ΅, Ρ‡Ρ‚ΠΎ Π² TPL Π΅ΡΡ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ стратСгиями распрСдСлСния Task’ов ΠΏΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ. Π’Π°ΠΊΠΈΠ΅ стратСгии ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ΡΡ Π² наслСдниках класса TaskScheduler. ΠŸΡ€Π°ΠΊΡ‚ΠΈΡ‡Π΅ΡΠΊΠΈ любая стратСгия, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ понадобится Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°ΠΉΠ΄Π΅Π½Π° Π² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅ ParallelExtensionsExtras, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Π½Π½ΠΎΠΉ microsoft, Π½ΠΎ Π½Π΅ ΡΠ²Π»ΡΡŽΡ‰Π΅ΠΉΡΡ Ρ‡Π°ΡΡ‚ΡŒΡŽ .NET, Π° ΠΏΠΎΡΡ‚Π°Π²Π»ΡΠ΅ΠΌΡƒΡŽ Π² Π²ΠΈΠ΄Π΅ Nuget ΠΏΠ°ΠΊΠ΅Ρ‚Π°. ΠšΠΎΡ€ΠΎΡ‚ΠΊΠΎ рассмотрим Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠ· Π½ΠΈΡ…:

  • CurrentThreadTaskScheduler β€” выполняСт Task’и Π½Π° Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅
  • LimitedConcurrencyLevelTaskScheduler β€” ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ число выполняСмых ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Task’ов ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ N, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π² конструкторС
  • OrderedTaskScheduler β€” опрСдСляСтся ΠΊΠ°ΠΊ LimitedConcurrencyLevelTaskScheduler(1), ΠΏΠΎΡ‚ΠΎΠΌΡƒ Π·Π°Π΄Π°Ρ‡ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ.
  • WorkStealingTaskScheduler β€” Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ work-stealing ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΠΊ Ρ€Π°ΡΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΡŽ Π·Π°Π΄Π°Ρ‡. По сути являСтся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ ThreadPool. Π Π΅ΡˆΠ°Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π² .NET ThreadPool это статичСский класс, ΠΎΠ΄ΠΈΠ½ Π½Π° всС прилоТСния, Π° Π·Π½Π°Ρ‡ΠΈΡ‚ Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΈΠ»ΠΈ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ использованиС Π² ΠΎΠ΄Π½ΠΎΠΉ части ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹ΠΌ эффСктам Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ. Π‘ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ³ΠΎ ΠΏΠΎΠ½ΡΡ‚ΡŒ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρƒ Ρ‚Π°ΠΊΠΈΡ… Π΄Π΅Ρ„Ρ„Π΅ΠΊΡ‚ΠΎΠ² ΠΊΡ€Π°ΠΉΠ½Π΅ слоТно. Π’.ΠΎ. ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ WorkStealingTaskScheduler’ы Π² Ρ‚Π΅Ρ… частях ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π³Π΄Π΅ использованиС ThreadPool ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ агрСссивным ΠΈ нСпрСдсказуСмым.
  • QueuedTaskScheduler β€” позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΏΠΎ ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ с ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚Π°ΠΌΠΈ
  • ThreadPerTaskScheduler β€” создаСт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Task Ρ‡Ρ‚ΠΎ Π½Π° Π½Π΅ΠΌ выполняСтся. ΠœΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для Π·Π°Π΄Π°Ρ‡ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰ΠΈΡ…ΡΡ нСпрСдсказуСмо Π΄ΠΎΠ»Π³ΠΎ.

Π•ΡΡ‚ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠ°Ρ подробная ΡΡ‚Π°Ρ‚ΡŒΡ ΠΎ TaskScheduler’ах Π² Π±Π»ΠΎΠ³Π΅ microsoft.

Для ΡƒΠ΄ΠΎΠ±Π½ΠΎΠΉ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ всСго связанного с Task’ами Π² Visual Studio Π΅ΡΡ‚ΡŒ ΠΎΠΊΠ½ΠΎ Tasks. Π’ этом ΠΎΠΊΠ½Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС Π·Π°Π΄Π°Ρ‡ΠΈ ΠΈ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ выполняСмой Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ строчкС ΠΊΠΎΠ΄Π°.

.NET: Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ. Π§Π°ΡΡ‚ΡŒ 1

PLinq и класс Parallel

ΠšΡ€ΠΎΠΌΠ΅ Task’ов ΠΈ всСго с Π½ΠΈΠΌΠΈ сказанного Π² .NET Π΅ΡΡ‚ΡŒ Π΅Ρ‰Π΅ Π΄Π²Π° интСрСсных инструмСнта это PLinq(Linq2Parallel) ΠΈ класс Parallel. ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠ±Π΅Ρ‰Π°Π΅Ρ‚ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ всСх Linq ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ…. Число ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ-Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ WithDegreeOfParallelism. К соТалСнию, Ρ‡Π°Ρ‰Π΅ всСго PLinq Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π½Π΅ Ρ…Π²Π°Ρ‚ΠΈΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ внутрСнностях вашСго источника Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ сущСствСнный Π²Ρ‹ΠΈΠ³Ρ€Ρ‹Ρˆ ΠΏΠΎ скорости, с Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороны Ρ†Π΅Π½Π° ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ ΠΎΡ‡Π΅Π½ΡŒ низкая: Π½ΡƒΠΆΠ½ΠΎ всСго лишь Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ AsParallel ΠΏΠ΅Ρ€Π΅Π΄ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΎΠΉ Linq ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ΠΈ провСсти тСсты ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. Π‘ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ³ΠΎ сущСствуСт Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π² PLinq Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Π΅ вашСго источника Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° Partitions. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ здСсь ΠΈ здСсь.

БтатичСский класс Parallel прСдоставляСт ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΠ΅Ρ€Π΅Π±ΠΎΡ€Π° ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Foreach, выполнСния Ρ†ΠΈΠΊΠ»Π° For ΠΈ выполнСния Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π΄Π΅Π»Π΅Π³Π°Ρ‚ΠΎΠ² Π² ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒ Invoke. Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π±ΡƒΠ΄Π΅Ρ‚ остановлСно Π΄ΠΎ окончания выполнСния расчСтов. ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Π² ParallelOptions послСдним Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ. Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΎΠΏΡ†ΠΈΠΉ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ TaskScheduler ΠΈ CancellationToken.

Π’Ρ‹Π²ΠΎΠ΄Ρ‹

Когда я Π½Π°Ρ‡ΠΈΠ½Π°Π» ΠΏΠΈΡΠ°Ρ‚ΡŒ эту ΡΡ‚Π°Ρ‚ΡŒΡŽ ΠΏΠΎ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π°ΠΌ своСго Π΄ΠΎΠΊΠ»Π°Π΄Π° ΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ Ρ‡Ρ‚ΠΎ собрал Π·Π° врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ послС Π½Π΅Π³ΠΎ, я Π½Π΅ ΠΎΠΆΠΈΠ΄Π°Π», Ρ‡Ρ‚ΠΎ Π΅Π΅ получится Ρ‚Π°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ. БСйчас, ΠΊΠΎΠ³Π΄Π° тСкстовый Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ я Π½Π°Π±ΠΈΡ€Π°ΡŽ эту ΡΡ‚Π°Ρ‚ΡŒΡŽ ΡƒΠΊΠΎΡ€ΠΈΠ·Π½Π΅Π½Π½ΠΎ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΌΠ½Π΅ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ пошла 15я страница, я ΠΏΠΎΠ΄Π²Π΅Π΄Ρƒ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹Π΅ ΠΈΡ‚ΠΎΠ³ΠΈ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ Ρ‚Ρ€ΡŽΠΊΠΈ, API, Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ инструмСнты ΠΈ ΠΏΠΎΠ΄Π²ΠΎΠ΄Π½Ρ‹Π΅ ΠΊΠ°ΠΌΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ рассмотрСны Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅.

Π’Ρ‹Π²ΠΎΠ΄Ρ‹:

  • НуТно Π·Π½Π°Ρ‚ΡŒ инструмСнты Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ, Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ рСсурсы соврСмСнных ПК.
  • Π’ .NET ΠΌΠ½ΠΎΠ³ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… инструмСнтов для этих Ρ†Π΅Π»Π΅ΠΉ
  • НС всС ΠΎΠ½ΠΈ появились сразу, ΠΏΠΎΡ‚ΠΎΠΌΡƒ часто ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΡ‚Ρ€Π΅Ρ‚ΠΈΡ‚ΡŒ legacy, Π²ΠΏΡ€ΠΎΡ‡Π΅ΠΌ Π΅ΡΡ‚ΡŒ способы для прСобразования старых API Π±Π΅Π· особых усилий.
  • Π Π°Π±ΠΎΡ‚Π° с ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ Π² .NET прСдставлСна классами Thread ΠΈ ThreadPool
  • ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ Thread.Abort, Thread.Interrupt, функция Win32 API TerminateThread опасны ΠΈ Π½Π΅ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽΡ‚ΡΡ ΠΊ использованию. ВмСсто Π½ΠΈΡ… Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ CancellationToken’ов
  • ΠŸΠΎΡ‚ΠΎΠΊ β€” Ρ†Π΅Π½Π½Ρ‹ΠΉ рСсурс, ΠΈΡ… количСство ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΎ. НуТно ΠΈΠ·Π±Π΅Π³Π°Ρ‚ΡŒ ситуаций, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΡ‚ΠΎΠΊΠΈ заняты ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ΠΌ событий. Для этого ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ класс TaskCompletionSource
  • НаиболСС ΠΌΠΎΡ‰Π½Ρ‹ΠΌ ΠΈ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚Ρ‹ΠΌ инструмСнтов .NET для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠΎΠΌ ΠΈ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒΡŽ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Task’и.
  • ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ c# async/await Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‚ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΡŽ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ оТидания
  • Π£ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ распрСдСлСниСм Task’ов ΠΏΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ ΠΌΠΎΠΆΠ½ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹Ρ… TaskScheduler’у классов
  • Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ValueTask ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»Π΅Π·Π½Π° Π² ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ hot-paths ΠΈ memory-traffic
  • Окна Tasks ΠΈ Threads Visual Studio ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ΠΈΠ»ΠΈ асинхронного ΠΊΠΎΠ΄Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ
  • PLinq ΠΊΡ€ΡƒΡ‚ΠΎΠΉ инструмСнт, Π½ΠΎ Ρƒ Π½Π΅Π³ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ Π±Ρ‹Ρ‚ΡŒ достаточно ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ вашСм источникС Π΄Π°Π½Π½Ρ‹Ρ…, Π²ΠΏΡ€ΠΎΡ‡Π΅ΠΌ это ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° partitioning
  • ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ слСдуСт…

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com