๋๋ Habr์ ์๋ณธ ๊ธฐ์ฌ๋ฅผ ๊ฒ์ํ๊ณ ์์ผ๋ฉฐ ๊ทธ ๋ฒ์ญ๋ณธ์ ๊ธฐ์
์ ๊ฒ์๋์ด ์์ต๋๋ค.
์ง๊ธ ์ฌ๊ธฐ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋น๋๊ธฐ์์ผ๋ก ์์
์ ์ํํ๊ฑฐ๋ ์ด๋ฅผ ์ํํ๋ ์ฌ๋ฌ ๋จ์์์ ๋๊ท๋ชจ ์์
์ ๋ถํ ํด์ผ ํ๋ ํ์์ฑ์ ์ปดํจํฐ๊ฐ ์ถํํ๊ธฐ ์ ์๋ ์กด์ฌํ์ต๋๋ค. ๊ทธ๋ค์ ์ถํ์ผ๋ก ์ด๋ฌํ ํ์์ฑ์ ๋งค์ฐ ๋ช
๋ฐฑํด์ก์ต๋๋ค. 2019๋
์ธ ์ง๊ธ, ์ ๋ 8๊ฐ ์ด์์ ํ๋ก์ธ์ค๊ฐ ๋ณ๋ ฌ๋ก ์คํ๋๊ณ ๋ ๋ง์ ์ค๋ ๋๊ฐ ์คํ๋๋ 8์ฝ์ด Intel Core ํ๋ก์ธ์๊ฐ ํ์ฌ๋ ๋
ธํธ๋ถ์์ ์ด ๊ธ์ ์์ฑํ๊ณ ์์ต๋๋ค. ๊ทผ์ฒ์๋ ๋ช ๋
์ ์ ๊ตฌ์
ํ ์ฝ๊ฐ ํ๋ฆํ ์ ํ๊ธฐ๊ฐ ์๋๋ฐ, ๊ทธ ์ ํ๊ธฐ์๋ 16์ฝ์ด ํ๋ก์ธ์๊ฐ ํ์ฌ๋์ด ์์ต๋๋ค. ์ฃผ์ ๋ณ ๋ฆฌ์์ค์๋ ์์ฑ์๊ฐ 20์ฝ์ด ํ๋ก์ธ์๋ฅผ ํ์ฌํ ์ฌํด์ ์ฃผ๋ ฅ ์ค๋งํธํฐ์ ์นญ์ฐฌํ๋ ๊ธฐ์ฌ์ ๋น๋์ค๊ฐ ๊ฐ๋ํฉ๋๋ค. MS Azure๋ ์๊ฐ๋น 128๋ฌ๋ฌ ๋ฏธ๋ง์ ๋น์ฉ์ผ๋ก 2์ฝ์ด ํ๋ก์ธ์์ XNUMXTB RAM์ ๊ฐ์ถ ๊ฐ์ ๋จธ์ ์ ์ ๊ณตํฉ๋๋ค. ๋ถํํ๊ฒ๋ ์ค๋ ๋์ ์ํธ ์์ฉ์ ๊ด๋ฆฌํ ์ ์์ผ๋ฉด ์ต๋์น๋ฅผ ์ถ์ถํ๊ณ ์ด ๊ธฐ๋ฅ์ ํ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ ๋ฌธ ์ฉ์ด
ํ๋ก์ธ์ค - ๊ฒฉ๋ฆฌ๋ ์ฃผ์ ๊ณต๊ฐ์ธ OS ๊ฐ์ฒด์๋ ์ค๋ ๋๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
์ค - OS ๊ฐ์ฒด, ์คํ์ ๊ฐ์ฅ ์์ ๋จ์, ํ๋ก์ธ์ค์ ์ผ๋ถ, ์ค๋ ๋๋ ํ๋ก์ธ์ค ๋ด์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐ ๊ธฐํ ๋ฆฌ์์ค๋ฅผ ๊ณต์ ํฉ๋๋ค.
๋ฉํฐ ํ์คํน - OS ์์ฑ, ์ฌ๋ฌ ํ๋ก์ธ์ค๋ฅผ ๋์์ ์คํํ๋ ๊ธฐ๋ฅ
๋ฉํฐ์ฝ์ด - ํ๋ก์ธ์์ ์์ฑ, ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํด ์ฌ๋ฌ ์ฝ์ด๋ฅผ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ
๋ค์ค ์ฒ๋ฆฌ - ์ปดํจํฐ์ ์์ฑ, ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ฌ๋ฌ ํ๋ก์ธ์์ ๋์์ ์์
ํ ์ ์๋ ๋ฅ๋ ฅ
๋ฉํฐ์ค๋ ๋ฉ โ ํ๋ก์ธ์ค์ ์์ฑ, ์ฌ๋ฌ ์ค๋ ๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ๋ถ์ฐ์ํค๋ ๊ธฐ๋ฅ์
๋๋ค.
๋ณํ - ๋จ์ ์๊ฐ๋น ์ฌ๋ฌ ์์
์ ๋์์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ํ
๋น๋๊ธฐ โ ์ด ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์์
์ ์คํํ๋ฉฐ, ์คํ ๊ฒฐ๊ณผ๋ ๋์ค์ ์ฒ๋ฆฌ๋ ์ ์์ต๋๋ค.
์์
๋ชจ๋ ์ ์๊ฐ ์ข์ ๊ฒ์ ์๋๋ฉฐ ์ผ๋ถ๋ ์ถ๊ฐ ์ค๋ช ์ด ํ์ํ๋ฏ๋ก ๊ณต์์ ์ผ๋ก ์๊ฐ๋ ์ฉ์ด์ ์์นจ ์์ฌ ์๋ฆฌ์ ๋ํ ๋น์ ๋ฅผ ์ถ๊ฐํ๊ฒ ์ต๋๋ค. ์ด ๋น์ ์์ ์์นจ ์์ฌ๋ฅผ ์๋ฆฌํ๋ ๊ฒ์ ํ๋์ ๊ณผ์ ์ ๋๋ค.
์์นจ์ ์์นจ์์ฌ๋ฅผ ์ค๋นํ๋ฉด์ ๋๋ (CPU) ๋๋ ๋ถ์์ ์จ๋ค (์ปดํจํฐ). ๋๋ ์์ด 2๊ฐ ์๋ค(์ฝ์ด). ์ฃผ๋ฐฉ์๋ ๋ค์ํ ๊ธฐ๊ธฐ๊ฐ ์์ต๋๋ค(IO): ์ค๋ธ, ์ฃผ์ ์, ํ ์คํฐ, ๋์ฅ๊ณ . ๊ฐ์ค๋ฅผ ์ผ๊ณ ๊ทธ ์์ ํ๋ผ์ดํฌ์ ์ฌ๋ ค๋๊ณ ์์ด๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๊ธฐ๋ฆ์ ๋ถ์ด์ค๋๋ค(๋น๋๊ธฐ์, Non-Blocking-IO-Wait), ๋์ฅ๊ณ ์์ ๊ณ๋์ ๊บผ๋ด์ ์ ์์ ๋ด์ ๋ค์ ํ ์์ผ๋ก ์น์ญ์์ค (์ค๋ ๋#1), ๋ ๋ฒ์งธ (์ค๋ ๋#2) ์ ์(๊ณต์ ์์)๋ฅผ ๋ค๊ณ ์์ต๋๋ค. ์ด์ ์ฃผ์ ์๋ฅผ ์ผ๊ณ ์ถ์๋ฐ ์์ด ๋ถ์กฑํด์.์ค๋ ๋ ๊ธฐ์) ์ด ์๊ฐ ๋์ ํ๋ผ์ดํฌ์ด ๊ฐ์ด๋์ด(๊ฒฐ๊ณผ ์ฒ๋ฆฌ ์ค) ํํํ ๊ฒ์ ๋ถ์ต๋๋ค. ๋๋ ์ฃผ์ ์์ ์์ ๋ป์ด ์ ์์ ์ผ๊ณ ์ด๋ฆฌ์๊ฒ๋ ๋ฌผ์ด ๋๋ ๊ฒ์ ์ง์ผ๋ด ๋๋ค.์ฐจ๋จ-IO-๋๊ธฐ), ๋น๋ก ์ด ์๊ฐ ๋์ ๊ทธ๋ ์ค๋ฏ๋ ์ ํ์ ๋ ์ ์๋ฅผ ์ป์ ์ ์์์ง๋ง.
๋ ์๋ง์ผ๋ก ์ค๋ฏ๋ ์ ์๋ฆฌํ๊ณ ๊ทธ ์ด์์ ์์ง๋ง ๋์์ ์ค๋ฏ๋ ์ ํ์ ๋ ์๊ฐ ์ค๋ฏ๋ ํํ, ์ ์ ์ก๊ธฐ, ํ๋ผ์ดํฌ ๊ฐ์ด์ ์ธ ๊ฐ์ง ์์ ์ด ํ ๋ฒ์ ์ด๋ฃจ์ด์ก์ต๋๋ค. CPU๋ ์ปดํจํฐ์์ ๊ฐ์ฅ ๋น ๋ฅธ ๋ถ๋ถ์ด๊ณ , IO๋ ๋ชจ๋ ๊ฒ์ด ๋๋ ค์ง๋ ๊ฒฝ์ฐ๊ฐ ๊ฐ์ฅ ๋ง๊ธฐ ๋๋ฌธ์ IO์์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๋์ CPU๋ฅผ ๋ฌด์ธ๊ฐ๋ก ์ ์ ํ๋ ๊ฒ์ด ํจ๊ณผ์ ์ธ ์๋ฃจ์ ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
๊ณ์ํด์ ๋น์ ํ์๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ค๋ฏ๋ ์ ๋ง๋๋ ๊ณผ์ ์์ ์ท๋ ๊ฐ์์ ์ด๋ณธ๋ค๋ฉด, ์ด๋ ๋ฉํฐํ์คํน์ ํ ์๊ฐ ๋ ๊ฒ์ด๋ค. ์ค์ํ ๋์์ค: ์ปดํจํฐ๋ ์ฌ๋๋ณด๋ค ์ด ๋ถ์ผ์์ ํจ์ฌ ๋ฐ์ด๋ฉ๋๋ค.
- ์๋ฅผ ๋ค์ด ๋ ์คํ ๋์ ์ฌ๋ฌ ์๋ฆฌ์ฌ๊ฐ ์๋ ์ฃผ๋ฐฉ - ๋ฉํฐ ์ฝ์ด ์ปดํจํฐ.
- ์ผํ ์ผํฐ์ ํธ๋ ์ฝํธ์ ์๋ ๋ง์ ๋ ์คํ ๋ - ๋ฐ์ดํฐ ์ผํฐ
.NET ๋๊ตฌ
.NET์ ๋ค๋ฅธ ๋ง์ ๊ฒ๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ค๋ ๋ ์์ ์ ๋ฅ์ํฉ๋๋ค. ์๋ก์ด ๋ฒ์ ์ด ๋์ฌ ๋๋ง๋ค ์์ ์ ์ํ ์ ์ ๋ ๋ง์ ์๋ก์ด ๋๊ตฌ, ์ฆ OS ์ค๋ ๋์ ๋ํ ์๋ก์ด ์ถ์ํ ๊ณ์ธต์ด ๋์ ๋ฉ๋๋ค. ์ถ์ํ ๊ตฌ์ฑ ์์ ์ ํ ๋ ํ๋ ์์ํฌ ๊ฐ๋ฐ์๋ ๋์ ์์ค์ ์ถ์ํ๋ฅผ ์ฌ์ฉํ ๋ ํ๋ ์ด์์ ์์ค ์๋๋ก ๋ด๋ ค๊ฐ ์ ์๋ ๊ธฐํ๋ฅผ ์ ๊ณตํ๋ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ด๋ ํ์ํ์ง ์์ต๋๋ค. ์ค์ ๋ก ์ฐํ์ด์ผ๋ก ์์ ์ ๋ฐ์ ์๋ ๋ฌธ์ด ์ด๋ฆฌ์ง๋ง ๋๋ก๋ ๋๋ฌธ ๊ฒฝ์ฐ์ง๋ง ํ์ฌ ์ถ์ํ ์์ค์์ ํด๊ฒฐ๋์ง ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ผ ์ ์์ต๋๋ค. .
๋๊ตฌ๋ ํ๋ ์์ํฌ์ ํ์ฌ ํจํค์ง์์ ์ ๊ณตํ๋ API(์์ฉ ํ๋ก๊ทธ๋๋ฐ ์ธํฐํ์ด์ค)๋ ๋ฌผ๋ก ๋ฉํฐ์ค๋ ๋ ์ฝ๋์ ๊ด๋ จ๋ ๋ฌธ์ ๊ฒ์์ ๋จ์ํํ๋ ์ ์ฒด ์ํํธ์จ์ด ์๋ฃจ์ ์ ์๋ฏธํฉ๋๋ค.
์ค๋ ๋ ์์ํ๊ธฐ
Thread ํด๋์ค๋ ์ค๋ ๋ ์์ ์ ์ํ .NET์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํด๋์ค์ ๋๋ค. ์์ฑ์๋ ๋ ๋๋ฆฌ์ ์ค ํ๋๋ฅผ ํ์ฉํฉ๋๋ค.
- ThreadStart โ ๋งค๊ฐ๋ณ์ ์์
- ParametrizedThreadStart - ๊ฐ์ฒด ์ ํ์ ๋งค๊ฐ๋ณ์๊ฐ ํ๋ ์์ต๋๋ค.
Start ๋ฉ์๋๋ฅผ ํธ์ถํ ํ ์๋ก ์์ฑ๋ ์ค๋ ๋์์ ๋๋ฆฌ์๊ฐ ์คํ๋ฉ๋๋ค. ParametrizedThreadStart ํ์์ ๋๋ฆฌ์๊ฐ ์์ฑ์์ ์ ๋ฌ๋ ๊ฒฝ์ฐ ๊ฐ์ฒด๊ฐ Start ๋ฉ์๋์ ์ ๋ฌ๋์ด์ผ ํฉ๋๋ค. ์ด ๋ฉ์ปค๋์ฆ์ ๋ก์ปฌ ์ ๋ณด๋ฅผ ์คํธ๋ฆผ์ผ๋ก ์ ์กํ๋ ๋ฐ ํ์ํฉ๋๋ค. ์ค๋ ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋น์ฉ์ด ๋ง์ด ๋๋ ์์ ์ด๋ฉฐ ์ค๋ ๋ ์์ฒด๋ ์ ์ด๋ ์คํ์ 1MB์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ณ OS API์์ ์ํธ ์์ฉ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ๋ฌด๊ฑฐ์ด ๊ฐ์ฒด๋ผ๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค.
new Thread(...).Start(...);
ThreadPool ํด๋์ค๋ ํ์ ๊ฐ๋ ์ ๋ํ๋ ๋๋ค. .NET์์ ์ค๋ ๋ ํ์ ์์ง๋์ด๋ง์ ์ผ๋ถ์ด๋ฉฐ Microsoft ๊ฐ๋ฐ์๋ ๋ค์ํ ์๋๋ฆฌ์ค์์ ์ต์ ์ผ๋ก ์๋ํ๋๋ก ๋ง์ ๋ ธ๋ ฅ์ ๊ธฐ์ธ์์ต๋๋ค.
์ผ๋ฐ ๊ฐ๋ :
์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋๋ ์๊ฐ๋ถํฐ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์๋น ์ค๋ ๋๋ฅผ ์ฌ๋ฌ ๊ฐ ์์ฑํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ค๋ ๋๊ฐ ์์ฃผ ๊ทธ๋ฆฌ๊ณ ๋๋์ผ๋ก ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ ํ์ ํธ์ถ์์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋๋ก ํ์ฅ๋ฉ๋๋ค. ์ ์์ ํ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ค๋ ๋๊ฐ ์์ผ๋ฉด ์ค๋ ๋ ์ค ํ๋๊ฐ ๋ฐํ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ ์ ์ค๋ ๋๋ฅผ ์์ฑํฉ๋๋ค. ๋ฐ๋ผ์ ์ค๋ ๋ ํ์ ์ผ๋ถ ๋จ๊ธฐ ์์ ์๋ ์ ํฉํ์ง๋ง ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ ์๋น์ค๋ก ์คํ๋๋ ์์ ์๋ ์ ํฉํ์ง ์์ต๋๋ค.
ํ์ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ParametrizedThreadStart์ ๋์ผํ ์๊ทธ๋์ฒ๋ฅผ ๊ฐ๋ WaitCallback ์ ํ์ ๋๋ฆฌ์๋ฅผ ํ์ฉํ๋ QueueUserWorkItem ๋ฉ์๋๊ฐ ์์ผ๋ฉฐ ์ฌ๊ธฐ์ ์ ๋ฌ๋ ๋งค๊ฐ ๋ณ์๋ ๋์ผํ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
ThreadPool.QueueUserWorkItem(...);
๋ ์๋ ค์ง ์ค๋ ๋ ํ ๋ฉ์๋ RegisterWaitForSingleObject๋ ๋น์ฐจ๋จ IO ์์ ์ ๊ตฌ์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๋ฉ์๋์ ์ ๋ฌ๋ ๋๋ฆฌ์๋ ๋ฉ์๋์ ์ ๋ฌ๋ WaitHandle์ด "Released"์ผ ๋ ํธ์ถ๋ฉ๋๋ค.
ThreadPool.RegisterWaitForSingleObject(...)
.NET์๋ ์ค๋ ๋ ํ์ด๋จธ๊ฐ ์์ผ๋ฉฐ ์ฒ๋ฆฌ๊ธฐ๊ฐ ํ์์ ๊ฐ์ ธ์จ ์ค๋ ๋์์ ํธ์ถ๋๋ค๋ ์ ์์ WinForms/WPF ํ์ด๋จธ์ ๋ค๋ฆ ๋๋ค.
System.Threading.Timer
์คํ์ ์ํด ํ์ ์ค๋ ๋์ ๋๋ฆฌ์๋ฅผ ๋ณด๋ด๋ ๋ค์ ์๋ค๋ฅธ ๋ฐฉ๋ฒ์ธ BeginInvoke ๋ฉ์๋๋ ์์ต๋๋ค.
DelegateInstance.BeginInvoke
์์ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์๋ ํจ์์ธ Kernel32.dll Win32 API์ CreateThread์ ๋ํด ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ๊ฒ ์ต๋๋ค. extern ๋ฉ์๋์ ๋ฉ์ปค๋์ฆ ๋๋ถ์ ์ด ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋๋ ๋ ๊ฑฐ์ ์ฝ๋์ ๋์ฐํ ์์์ ๊ทธ๋ฌํ ํธ์ถ์ ๋จ ํ ๋ฒ ๋ณธ ์ ์ด ์์ผ๋ฉฐ, ์ ํํ ์ด๊ฒ์ ํ ์์ฑ์์ ๋๊ธฐ๋ ์ฌ์ ํ ๋์๊ฒ ๋ฏธ์คํฐ๋ฆฌ๋ก ๋จ์ ์์ต๋๋ค.
Kernel32.dll CreateThread
์ค๋ ๋ ๋ณด๊ธฐ ๋ฐ ๋๋ฒ๊น
์ฌ์ฉ์๊ฐ ๋ง๋ ์ค๋ ๋, ๋ชจ๋ ํ์ฌ ๊ตฌ์ฑ ์์ ๋ฐ .NET ํ์ Visual Studio์ ์ค๋ ๋ ์ฐฝ์์ ๋ณผ ์ ์์ต๋๋ค. ์ด ์ฐฝ์ ์์ฉ ํ๋ก๊ทธ๋จ์ด ๋๋ฒ๊ทธ ์ํ์ด๊ณ ์ค๋จ ๋ชจ๋์ ์์ ๋๋ง ์ค๋ ๋ ์ ๋ณด๋ฅผ ํ์ํฉ๋๋ค. ์ฌ๊ธฐ์์ ๊ฐ ์ค๋ ๋์ ์คํ ์ด๋ฆ๊ณผ ์ฐ์ ์์๋ฅผ ํธ๋ฆฌํ๊ฒ ํ์ธํ๊ณ ๋๋ฒ๊น ์ ํน์ ์ค๋ ๋๋ก ์ ํํ ์ ์์ต๋๋ค. Thread ํด๋์ค์ Priority ์์ฑ์ ์ฌ์ฉํ๋ฉด OC์ CLR์ด ์ค๋ ๋ ๊ฐ์ ํ๋ก์ธ์ ์๊ฐ์ ๋๋ ๋ ๊ถ์ฅ ์ฌํญ์ผ๋ก ์ธ์ํ๋ ์ค๋ ๋์ ์ฐ์ ์์๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
ํ์คํฌ ๋ณ๋ ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
TPL(์์ ๋ณ๋ ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)์ .NET 4.0์ ๋์ ๋์์ต๋๋ค. ์ด์ ์ด๋ ๋น๋๊ธฐ ์์ ์ ์ํ ํ์ค์ด์ ์ฃผ์ ๋๊ตฌ์ ๋๋ค. ์ด์ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๋ชจ๋ ์ฝ๋๋ ๋ ๊ฑฐ์๋ก ๊ฐ์ฃผ๋ฉ๋๋ค. TPL์ ๊ธฐ๋ณธ ๋จ์๋ System.Threading.Tasks ๋ค์์คํ์ด์ค์ Task ํด๋์ค์ ๋๋ค. ์์ ์ ์ค๋ ๋์ ๋ํ ์ถ์ํ์ ๋๋ค. ์๋ก์ด ๋ฒ์ ์ C# ์ธ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ์์ (async/await ์ฐ์ฐ์)์ ์ฌ์ฉํ์ฌ ์์ ํ ์ ์๋ ์ฐ์ํ ๋ฐฉ๋ฒ์ด ์๊ฒผ์ต๋๋ค. ์ด๋ฌํ ๊ฐ๋ ๋๋ถ์ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ๊ฐ๋จํ๊ณ ๋๊ธฐ์ ์ธ ๊ฒ์ฒ๋ผ ์์ฑํ ์ ์๊ฒ ๋์๊ณ , ์ค๋ ๋์ ๋ด๋ถ ์๋์ ๋ํด ๊ฑฐ์ ์ดํดํ์ง ๋ชปํ ์ฌ๋์ด๋ผ๋ ์ด๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ , ๊ธด ์์ ์ ์ํํ ๋ ๋ฉ์ถ์ง ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํ ์ ์๊ฒ ๋์์ต๋๋ค. async/await ์ฌ์ฉ์ ํ๋ ๋๋ ์ฌ๋ฌ ๊ธฐ์ฌ์ ์ฃผ์ ์ด์ง๋ง ๋ช ๋ฌธ์ฅ์ผ๋ก ์์ ์ ํ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
- async๋ Task ๋๋ void๋ฅผ ๋ฐํํ๋ ๋ฉ์๋์ ์์ ์์ ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ wait๋ ๋น์ฐจ๋จ ์์ ๋๊ธฐ ์ฐ์ฐ์์ ๋๋ค.
๋ค์ ํ ๋ฒ ๋ง์๋๋ฆฌ์ง๋ง, ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ(์์ธ๊ฐ ์์) wait ์ฐ์ฐ์๋ ํ์ฌ ์คํ ์ค๋ ๋๋ฅผ ์ถ๊ฐ๋ก ํด์ ํ๊ณ ์์ ์ด ์คํ์ ๋ง์น๋ฉด ์ค๋ ๋(์ค์ ๋ก ์ปจํ ์คํธ๋ฅผ ๋งํ๋ ๊ฒ์ด ๋ ์ ํํฉ๋๋ค)๋ฅผ ํด์ ํฉ๋๋ค. , ๋์ค์ ์์ธํ ์ค๋ช ) ๋ฉ์๋๋ฅผ ๊ณ์ํด์ ์คํํฉ๋๋ค. .NET ๋ด์์ ์ด ๋ฉ์ปค๋์ฆ์ ์์ฑ๋ ๋ฉ์๋๊ฐ ์ ์ฒด ํด๋์ค๋ก ๋ฐ๋ ๋ ํญ๋ณต ๋ฐํ๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ๊ตฌํ๋ฉ๋๋ค. ์ด๋ ์ํ ๋จธ์ ์ด๋ฉฐ ์ด๋ฌํ ์ํ์ ๋ฐ๋ผ ๋ณ๋์ ์กฐ๊ฐ์ผ๋ก ์คํ๋ ์ ์์ต๋๋ค. ๊ด์ฌ ์๋ ์ฌ๋์ ๋๊ตฌ๋ asynั/await๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์ฝ๋๋ฅผ ์์ฑํ๊ณ , ์ปดํ์ผ๋ฌ ์์ฑ ์ฝ๋๊ฐ ํ์ฑํ๋ JetBrains dotPeek์ ์ฌ์ฉํ์ฌ ์ด์ ๋ธ๋ฆฌ๋ฅผ ์ปดํ์ผํ๊ณ ๋ณผ ์ ์์ต๋๋ค.
Task๋ฅผ ์์ํ๊ณ ์ฌ์ฉํ๊ธฐ ์ํ ์ต์ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์๋ ์ฝ๋ ์์ ์์๋ ์ ์ฉํ์ง ์์ ์ ์์ ์ ๋ง๋ญ๋๋ค(์ค๋ ๋.์๋ฉด(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
}
ํ์คํฌ๋ ๋ค์๊ณผ ๊ฐ์ ๋ค์ํ ์ต์ ์ผ๋ก ์์ฑ๋ฉ๋๋ค.
- LongRunning์ ์์ ์ด ๋นจ๋ฆฌ ์๋ฃ๋์ง ์์ ๊ฒ์ด๋ผ๋ ํํธ์ ๋๋ค. ์ฆ, ํ์์ ์ค๋ ๋๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์๋๋ผ ๋ค๋ฅธ ์ฌ๋์๊ฒ ํด๋ฅผ ๋ผ์น์ง ์๋๋ก ์ด ์์ ์ ๋ํด ๋ณ๋์ ์ค๋ ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
- AttachedToParent - ์์ ์ ๊ณ์ธต ๊ตฌ์กฐ๋ก ์ ๋ ฌํ ์ ์์ต๋๋ค. ์ด ์ต์ ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ Task๋ ์์ฒด์ ์ผ๋ก ์๋ฃ๋์ด ํ์ ํญ๋ชฉ์ ์คํ์ ๊ธฐ๋ค๋ฆฌ๋ ์ํ์ผ ์ ์์ต๋๋ค.
- PreferFairness - ์คํ์ ์ํด ์ ์ก๋ ํ์คํฌ๋ฅผ ๋์ค์ ์ ์กํ๊ธฐ ์ ์ ๋จผ์ ์คํํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ๋จ์ง ๊ถ์ฅ์ฌํญ์ผ ๋ฟ์ด๋ฉฐ ๊ฒฐ๊ณผ๋ ๋ณด์ฅ๋์ง ์์ต๋๋ค.
๋ฉ์๋์ ์ ๋ฌ๋ ๋ ๋ฒ์งธ ๋งค๊ฐ ๋ณ์๋ CancellationToken์ ๋๋ค. ์์ ์ด ์์๋ ํ ์์ ์ทจ์๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ ค๋ฉด ์คํ ์ค์ธ ์ฝ๋๋ฅผ CancellationToken ์ํ์ ๋ํ ๊ฒ์ฌ๋ก ์ฑ์์ผ ํฉ๋๋ค. ๊ฒ์ฌ๊ฐ ์์ผ๋ฉด CancellationTokenSource ๊ฐ์ฒด์์ ํธ์ถ๋ Cancel ๋ฉ์๋๋ ์์ ์ด ์์๋๊ธฐ ์ ์๋ง ์์ ์คํ์ ์ค์งํ ์ ์์ต๋๋ค.
๋ง์ง๋ง ๋งค๊ฐ๋ณ์๋ TaskScheduler ์ ํ์ ์ค์ผ์ค๋ฌ ๊ฐ์ฒด์ ๋๋ค. ์ด ํด๋์ค์ ๊ทธ ํ์ ํญ๋ชฉ์ ์ค๋ ๋ ์ ์ฒด์ ์์ ์ ๋ฐฐํฌํ๊ธฐ ์ํ ์ ๋ต์ ์ ์ดํ๋๋ก ์ค๊ณ๋์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์์ ์ ํ์ ์์ ์ค๋ ๋์์ ์คํ๋ฉ๋๋ค.
Wait ์ฐ์ฐ์๋ ์์ฑ๋ ์์ ์ ์ ์ฉ๋ฉ๋๋ค. ์ฆ, ๊ทธ ๋ค์ ์์ฑ๋ ์ฝ๋๊ฐ ๋๊ธฐ ์ ์ ์ฝ๋์ ๋์ผํ ์ปจํ ์คํธ(์ข ์ข ๋์ผํ ์ค๋ ๋์์ ์คํ๋จ)์์ ์คํ๋๋ค๋ ์๋ฏธ์ ๋๋ค.
๋ฉ์๋๋ async void๋ก ํ์๋ฉ๋๋ค. ์ฆ, wait ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ํธ์ถ ์ฝ๋๋ ์คํ์ ๊ธฐ๋ค๋ฆด ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ด ํ์ํ ๊ฒฝ์ฐ ๋ฉ์๋๋ Task๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค. async void๋ก ํ์๋ ๋ฉ์๋๋ ๋งค์ฐ ์ผ๋ฐ์ ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ด๋ ํ์ฌ ๋ฐ ๋ง๊ฐ ์์น์ ๋ฐ๋ผ ์๋ํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋๋ ๊ธฐํ ๋ฉ์๋์ ๋๋ค. ์คํ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆด ์ ์๋ ๊ธฐํ๋ฅผ ์ ๊ณตํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํด์ผ ํ๋ ๊ฒฝ์ฐ Task๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
StartNew ๋ฉ์๋๊ฐ ๋ฐํํ ์์ ๊ณผ ๋ค๋ฅธ ๋ชจ๋ ์์ ์์ false ๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ConfigureAwait ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋๊ธฐ ํ ์คํ์ ์บก์ฒ๋ ์ปจํ ์คํธ๊ฐ ์๋ ์์์ ์ปจํ ์คํธ์์ ๊ณ์๋ฉ๋๋ค. ์ด๋ ๋๊ธฐ ํ ์ฝ๋์ ๋ํด ์คํ ์ปจํ ์คํธ๊ฐ ์ค์ํ์ง ์์ ๊ฒฝ์ฐ ํญ์ ์ํ๋์ด์ผ ํฉ๋๋ค. ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํจํค์ง๋์ด ์ ๊ณต๋ ์ฝ๋๋ฅผ ์์ฑํ ๋ MS์์ ๊ถ์ฅํ๋ ์ฌํญ์ด๊ธฐ๋ ํฉ๋๋ค.
์์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ข ๋ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๋ค์์ ๊ธฐ๋๊ฐ ์กฐ๊ฑด์ ์ผ๋ก ์ ์ํ๋๋ ๊ฒฝ์ฐ์ ์กฐ๊ฑด์ ์ผ๋ก ์๋ชป ์ํ๋๋ ๊ฒฝ์ฐ์ ๋ํ ์ค๋ช ์ด ํฌํจ๋ ์ฝ๋์ ์์ ๋๋ค.
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
}
์ฒซ ๋ฒ์งธ ์์์๋ ํธ์ถ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ๊ฒฐ๊ณผ๊ฐ ์ด๋ฏธ ์๋ ๊ฒฝ์ฐ์๋ง ๊ฒฐ๊ณผ ์ฒ๋ฆฌ๋ก ๋์๊ฐ๋๋ค. ๊ทธ๋๊น์ง ํธ์ถ ์ค๋ ๋๋ ์์ฒด ์ฅ์น์ ๋จ์ ์์ต๋๋ค.
๋ ๋ฒ์งธ ์ต์ ์์๋ ๋ฉ์๋ ๊ฒฐ๊ณผ๊ฐ ๊ณ์ฐ๋ ๋๊น์ง ํธ์ถ ์ค๋ ๋๋ฅผ ์ฐจ๋จํฉ๋๋ค. ์ด๋ ํ๋ก๊ทธ๋จ์ ๊ท์คํ ๋ฆฌ์์ค์ธ ์ค๋ ๋๋ฅผ ๋จ์ํ ์ ํด ์ํ๋ก ์ ์ ํ์ ๋ฟ๋ง ์๋๋ผ ์ฐ๋ฆฌ๊ฐ ํธ์ถํ๋ ๋ฉ์๋์ ์ฝ๋์ ๋๊ธฐ๊ฐ ํฌํจ๋์ด ์๊ณ ๋๊ธฐํ ์ปจํ ์คํธ๊ฐ ์ดํ ํธ์ถ ์ค๋ ๋๋ก ๋ฐํํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ข์ง ์์ต๋๋ค. ๊ธฐ๋ค๋ฆฌ๋ฉด ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํฉ๋๋ค. ํธ์ถ ์ค๋ ๋๋ ๋น๋๊ธฐ ๋ฉ์๋์ ๊ฒฐ๊ณผ๊ฐ ๊ณ์ฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ , ๋น๋๊ธฐ ๋ฉ์๋๋ ํธ์ถ ์ค๋ ๋์์ ์คํ์ ๊ณ์ํ๋ ค๊ณ ์๋ํ์ง๋ง ์คํจํฉ๋๋ค.
์ด ์ ๊ทผ ๋ฐฉ์์ ๋ ๋ค๋ฅธ ๋จ์ ์ ๋ณต์กํ ์ค๋ฅ ์ฒ๋ฆฌ์ ๋๋ค. ์ฌ์ค async/await๋ฅผ ์ฌ์ฉํ ๋ ๋น๋๊ธฐ ์ฝ๋์ ์ค๋ฅ๋ ์ฒ๋ฆฌํ๊ธฐ๊ฐ ๋งค์ฐ ์ฝ์ต๋๋ค. ์ค๋ฅ๋ ์ฝ๋๊ฐ ๋๊ธฐ์ธ ๊ฒ์ฒ๋ผ ๋์ผํ๊ฒ ๋์ํฉ๋๋ค. Task์ ๋๊ธฐ์ ๋๊ธฐ ์์์์ฆ์ ์ ์ฉํ๋ฉด ์๋ ์์ธ๋ AggregateException์ผ๋ก ๋ณํฉ๋๋ค. ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ค๋ฉด InnerException ์ ํ์ ๊ฒ์ฌํ๊ณ C# ์ธ๊ณ์์ ๋ ์น์ํ catch ๋ธ๋ก ์ฒด์ธ ๋์ ํ๋์ catch ๋ธ๋ก ๋ด์ if ์ฒด์ธ์ ์ง์ ์์ฑํ๊ฑฐ๋ catch when ๊ตฌ๋ฌธ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
์ธ ๋ฒ์งธ์ ๋ง์ง๋ง ์์ ๋ ๊ฐ์ ์ด์ ๋ก ๋ถ๋์ผ๋ก ํ์๋์์ผ๋ฉฐ ๋ชจ๋ ๋์ผํ ๋ฌธ์ ๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค.
WhenAny ๋ฐ WhenAll ๋ฉ์๋๋ ์์ ๊ทธ๋ฃน์ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค. ์์ ๊ทธ๋ฃน์ ํ๋๋ก ๋ํํ์ฌ ๊ทธ๋ฃน์ ์์ ์ด ์ฒ์ ํธ๋ฆฌ๊ฑฐ๋๊ฑฐ๋ ๋ชจ๋ ์์ ์ด ์คํ์ ์๋ฃํ์ ๋ ์คํ๋ฉ๋๋ค.
์ค๋ ๋ ์ค์ง
๋ค์ํ ์ด์ ๋ก ํ๋ฆ์ด ์์๋ ํ ํ๋ฆ์ ์ค์งํด์ผ ํ ์๋ ์์ต๋๋ค. ์ด๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์๋ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค. Thread ํด๋์ค์๋ ์ ์ ํ๊ฒ ์ด๋ฆ์ด ์ง์ ๋ ๋ ๊ฐ์ง ๋ฉ์๋๊ฐ ์์ต๋๋ค. ์ ์ฐ ะธ ์ธํฐ๋ฝํธ. ์ฒซ ๋ฒ์งธ๋ ์ฌ์ฉ์ ๊ถ์ฅํ์ง ์์ต๋๋ค. ์์์ ์๊ฐ์ ํธ์ถํ ํ ๋ช ๋ น์ ์ฒ๋ฆฌํ๋ ๋์ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค. ThreadAbortedException. ์ ์ ๋ณ์๋ฅผ ์ฆ๊ฐ์ํฌ ๋ ์ด๋ฌํ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ผ๊ณ ๋ ์์ํ์ง ์์ต๋๋ค. ๊ทธ๋ ์ฃ ? ๊ทธ๋ฆฌ๊ณ ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ์ด๋ ๋งค์ฐ ์ค์ ์ ์ธ ์ํฉ์ ๋๋ค. CLR์ด ์ฝ๋์ ํน์ ์น์ ์์ ์ด๋ฌํ ์์ธ๋ฅผ ์์ฑํ์ง ๋ชปํ๋๋ก ํด์ผ ํ๋ ๊ฒฝ์ฐ ์ด๋ฅผ ํธ์ถ๋ก ๋ํํ ์ ์์ต๋๋ค. Thread.BeginCriticalRegion, Thread.EndCriticalRegion. finally ๋ธ๋ก์ ์์ฑ๋ ๋ชจ๋ ์ฝ๋๋ ์ด๋ฌํ ํธ์ถ๋ก ๋ํ๋ฉ๋๋ค. ์ด๋ฌํ ์ด์ ๋ก ํ๋ ์์ํฌ ์ฝ๋์ ๊น์ด์์ ๋น try๊ฐ ์๋ ๋ธ๋ก์ ์ฐพ์ ์ ์์ง๋ง finally๋ ๋น์ด ์์ง ์์ต๋๋ค. Microsoft๋ ์ด ๋ฐฉ๋ฒ์ ๋๋ฌด ๊ถ์ฅํ์ง ์์ .net ์ฝ์ด์ ํฌํจํ์ง ์์์ต๋๋ค.
์ธํฐ๋ฝํธ ๋ฐฉ๋ฒ์ ๋ ์์ธก ๊ฐ๋ฅํ๊ฒ ์๋ํฉ๋๋ค. ์์ธ๋ก ์ธํด ์ค๋ ๋๋ฅผ ์ค๋จํ ์ ์์ต๋๋ค. ThreadInterruptedException ์ค๋ ๋๊ฐ ๋๊ธฐ ์ํ์ ์๋ ์๊ฐ์๋ง ๊ฐ๋ฅํฉ๋๋ค. WaitHandle, ์ ๊ธ์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋๋ Thread.Sleep์ ํธ์ถํ ํ ์ ์ง๋๋ ๋์ ์ด ์ํ๋ก ๋ค์ด๊ฐ๋๋ค.
์์ ์ค๋ช ๋ ๋ ์ต์ ๋ชจ๋ ์์ธก ๋ถ๊ฐ๋ฅ์ฑ์ผ๋ก ์ธํด ์ข์ง ์์ต๋๋ค. ํด๊ฒฐ์ฑ ์ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ์ทจ์ ํ ํฐ ๊ทธ๋ฆฌ๊ณ ์์ ์ทจ์ ํ ํฐ ์์ค. ์์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. CancellationTokenSource ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์์ฑ๋๊ณ ์ด๋ฅผ ์์ ํ ์ฌ๋๋ง ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์์ ์ ์ค์งํ ์ ์์ต๋๋ค. ์ทจ์. CancellationToken๋ง ์์ ์์ฒด์ ์ ๋ฌ๋ฉ๋๋ค. CancellationToken ์์ ์๋ ์์ ์ ์ง์ ์ทจ์ํ ์ ์์ผ๋ฉฐ ์์ ์ด ์ทจ์๋์๋์ง ์ฌ๋ถ๋ง ํ์ธํ ์ ์์ต๋๋ค. ์ด์ ๋ํ ๋ถ์ธ ์์ฑ์ด ์์ต๋๋ค. ์ทจ์์์ฒญ๋จ ๋ฐ ๋ฐฉ๋ฒ ThrowIfCancel์์ฒญ๋จ. ํ์๋ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค TaskCancelledException Parroting ์ค์ธ CancellationToken ์ธ์คํด์ค์์ Cancel ๋ฉ์๋๊ฐ ํธ์ถ๋ ๊ฒฝ์ฐ. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ด ์ ๊ฐ ์ถ์ฒํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ ์์ธ ์์ ์ ์ค๋จํ ์ ์๋ ์ง์ ์ ์์ ํ ์ ์ดํจ์ผ๋ก์จ ์ด์ ์ต์ ์ ๋นํด ๊ฐ์ ๋ ๊ฒ์ ๋๋ค.
์ค๋ ๋๋ฅผ ์ค์งํ๋ ๊ฐ์ฅ ์์ธํ ์ต์ ์ Win32 API TerminateThread ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋๋ค. ์ด ํจ์๋ฅผ ํธ์ถํ ํ CLR์ ๋์์ ์์ธกํ ์ ์์ต๋๋ค. MSDN์๋ ์ด ํจ์์ ๋ํด ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ด ๊ธฐ๋ก๋์ด ์์ต๋๋ค. โTerminateThread๋ ๊ฐ์ฅ ๊ทน๋จ์ ์ธ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํด์ผ ํ๋ ์ํํ ๊ธฐ๋ฅ์ ๋๋ค. โ
FromAsync ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๊ฑฐ์ API๋ฅผ ์์ ๊ธฐ๋ฐ์ผ๋ก ๋ณํ
ํ์คํฌ๊ฐ ๋์ ๋ ํ ์์๋์ด ๋๋ถ๋ถ์ ๊ฐ๋ฐ์์๊ฒ ์กฐ์ฉํ ๊ณตํฌ๊ฐ์ ์๊ฒจ์ค ํ๋ก์ ํธ๋ฅผ ์ด ์ข๊ฒ ์์ ํ ์ ์๋ค๋ฉด ํ์ฌ API์ ํ API ๋ชจ๋๋ฅผ ํฌํจํ ๋ง์ ์ค๋๋ API๋ฅผ ์ฒ๋ฆฌํ ํ์๊ฐ ์์ต๋๋ค. ๊ณผ๊ฑฐ์ ๊ณ ๋ฌธ์ ๊ฐํ ์ ์ด ์๋ค. ์ด ์ข๊ฒ๋ .NET Framework ํ์ด ์ฐ๋ฆฌ๋ฅผ ๋๋ด์ฃผ์์ง๋ง ์๋ง๋ ๋ชฉํ๋ ์ฐ๋ฆฌ ์์ ์ ๋๋ณด๋ ๊ฒ์ด์์ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ .NET์๋ ๊ธฐ์กด ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์์ฑ๋ ์ฝ๋๋ฅผ ์๋ก์ด ์ฝ๋๋ก ์ฝ๊ฒ ๋ณํํ ์ ์๋ ๋ค์ํ ๋๊ตฌ๊ฐ ์์ต๋๋ค. ๊ทธ ์ค ํ๋๊ฐ TaskFactory์ FromAsync ๋ฉ์๋์ ๋๋ค. ์๋ ์ฝ๋ ์์ ์์๋ ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ WebRequest ํด๋์ค์ ์ด์ ๋น๋๊ธฐ ๋ฉ์๋๋ฅผ ์์ ์ผ๋ก ๋ํํฉ๋๋ค.
object state = null;
WebRequest wr = WebRequest.CreateHttp("http://github.com");
await Task.Factory.FromAsync(
wr.BeginGetResponse,
we.EndGetResponse
);
์ด๊ฒ์ ๋จ์ง ์์ผ ๋ฟ์ด๋ฉฐ ๊ธฐ๋ณธ ์ ๊ณต ์ ํ์ ์ฌ์ฉํ์ฌ ์ด ์์ ์ ์ํํ ํ์๋ ์์ง๋ง ๊ธฐ์กด ํ๋ก์ ํธ์๋ IAsyncResult๋ฅผ ๋ฐํํ๋ BeginDoSomething ๋ฉ์๋์ ์ด๋ฅผ ์์ ํ๋ EndDoSomething ๋ฉ์๋๊ฐ ๋์ณ๋ฉ๋๋ค.
TaskCompletionSource ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๊ฑฐ์ API๋ฅผ ์์ ๊ธฐ๋ฐ์ผ๋ก ๋ณํ
๊ณ ๋ คํด์ผ ํ ๋ ๋ค๋ฅธ ์ค์ํ ๋๊ตฌ๋ ํด๋์ค์ ๋๋ค. ์์ ์๋ฃ์์ค. ๊ธฐ๋ฅ, ๋ชฉ์ , ์๋ ์๋ฆฌ ์ธก๋ฉด์์ ๋ณด๋ฉด ์์์ ์ธ๊ธํ ThreadPool ํด๋์ค์ RegisterWaitForSingleObject ๋ฉ์๋์ ๋ค์ ์ ์ฌํ ์ ์์ต๋๋ค. ์ด ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ์กด ๋น๋๊ธฐ API๋ฅผ ์์ ์์ ์ฝ๊ณ ํธ๋ฆฌํ๊ฒ ๋ํํ ์ ์์ต๋๋ค.
์ด๋ฌํ ๋ชฉ์ ์ ์ํด ๊ณ ์๋ TaskFactory ํด๋์ค์ FromAsync ๋ฉ์๋์ ๋ํด ์ด๋ฏธ ์ด์ผ๊ธฐํ๋ค๊ณ ๋งํ ๊ฒ์ ๋๋ค. ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ Microsoft๊ฐ ์ง๋ 15๋ ๋์ ์ ๊ณตํ .net์ ๋น๋๊ธฐ ๋ชจ๋ธ ๊ฐ๋ฐ์ ์ ์ฒด ์ญ์ฌ๋ฅผ ๊ธฐ์ตํด์ผ ํฉ๋๋ค. TAP(์์ ๊ธฐ๋ฐ ๋น๋๊ธฐ ํจํด) ์ด์ ์๋ APP(๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ํจํด)๊ฐ ์์์ต๋๋ค. ๋ฐฉ๋ฒ์ ๊ดํ ๊ฒ์ด์์ด ์์DoSomething์ด ๋์์ค๊ณ ์์ต๋๋ค. IAsyncResult ๋ฐ ๋ฐฉ๋ฒ ์ข ๋ฃ์ด๋ฅผ ๋ฐ์๋ค์ด๋ DoSomething๊ณผ ์ง๋ ๋ช ๋ ๋์ FromAsync ๋ฉ์๋๋ ์๋ฒฝํ์ง๋ง ์๊ฐ์ด ์ง๋๋ฉด์ ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋น๋๊ธฐ ํจํด(EAP), ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋๋ฉด ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค๊ณ ๊ฐ์ ํ์ต๋๋ค.
TaskCompletionSource๋ ์ด๋ฒคํธ ๋ชจ๋ธ์ ์ค์ฌ์ผ๋ก ๊ตฌ์ถ๋ ์์ ๋ฐ ๋ ๊ฑฐ์ API๋ฅผ ๋ํํ๋ ๋ฐ ์ ํฉํฉ๋๋ค. ํด๋น ์์ ์ ๋ณธ์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ด ํด๋์ค์ ๊ฐ์ฒด์๋ Task ์ ํ์ ๊ณต์ฉ ์์ฑ์ด ์์ผ๋ฉฐ, ํด๋น ์ํ๋ TaskCompletionSource ํด๋์ค์ SetResult, SetException ๋ฑ ๋ฉ์๋๋ฅผ ํตํด ์ ์ด๋ ์ ์์ต๋๋ค. ์ด Task์ Wait ์ฐ์ฐ์๊ฐ ์ ์ฉ๋ ์์น์์๋ TaskCompletionSource์ ์ ์ฉ๋ ๋ฉ์๋์ ๋ฐ๋ผ ์์ธ๊ฐ ๋ฐ์ํ์ฌ ์คํ๋๊ฑฐ๋ ์คํจํฉ๋๋ค. ์ฌ์ ํ ๋ช ํํ์ง ์๋ค๋ฉด ์ผ๋ถ ์ด์ EAP API๊ฐ TaskCompletionSource๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ๋ํ๋ ์ด ์ฝ๋ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์์ ์ด ์๋ฃ๋จ ์ํ๋ก ์ ํ๋๊ณ ๋๊ธฐ ์ฐ์ฐ์๋ฅผ ์ ์ฉํ ๋ฉ์๋๊ฐ ํ์๋ฉ๋๋ค. ์ด ํ์คํฌ๋ ๊ฐ์ฒด๋ฅผ ์์ ํ ํ ์คํ์ ์ฌ๊ฐํฉ๋๋ค. ๊ฒฐ๊ณผ.
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๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ API๋ฅผ ๋ํํ๋ ๊ฒ์ด ์ ๋ถ๋ ์๋๋๋ค. ์ด ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ค๋ ๋๋ฅผ ์ฐจ์งํ์ง ์๋ ์์ ์ ๋ํ ๋ค์ํ API๋ฅผ ์ค๊ณํ ์ ์๋ ํฅ๋ฏธ๋ก์ด ๊ฐ๋ฅ์ฑ์ด ์ด๋ฆฝ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๊ฐ ๊ธฐ์ตํ๋ ๊ฒ์ฒ๋ผ ์คํธ๋ฆผ์ ๊ฐ ๋น์ผ ๋ฆฌ์์ค์ด๋ฉฐ ๊ทธ ์๋ ์ฃผ๋ก RAM ์์ ๋ฐ๋ผ ์ ํ๋ฉ๋๋ค. ์ด๋ฌํ ์ ํ์ ์๋ฅผ ๋ค์ด ๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง์ด ํฌํจ๋ ๋ก๋๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํจ์ผ๋ก์จ ์ฝ๊ฒ ๋ฌ์ฑ๋ ์ ์์ต๋๋ค. Long-Polling๊ณผ ๊ฐ์ ํธ๋ฆญ์ ๊ตฌํํ ๋ ๋ด๊ฐ ๋งํ๋ ๊ฐ๋ฅ์ฑ์ ๊ณ ๋ คํด ๋ณด๊ฒ ์ต๋๋ค.
์์ปจ๋ ํธ๋ฆญ์ ๋ณธ์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. API ์ธก์์ ๋ฐ์ํ๋ ์ผ๋ถ ์ด๋ฒคํธ์ ๋ํ ์ ๋ณด๋ฅผ API๋ก๋ถํฐ ๋ฐ์์ผ ํ๋ ๋ฐ๋ฉด, API๋ ์ด๋ค ์ด์ ๋ก ์ด๋ฒคํธ๋ฅผ ๋ณด๊ณ ํ ์ ์๊ณ ์ํ๋ง ๋ฐํํ ์ ์์ต๋๋ค. ์ด์ ๋ํ ์๋ WebSocket ์๋ ์ด์ ์ด๋ ์ด๋ค ์ด์ ๋ก ์ด ๊ธฐ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ์ ๋ HTTP ์์ ๊ตฌ์ถ๋ ๋ชจ๋ API์ ๋๋ค. ํด๋ผ์ด์ธํธ๋ HTTP ์๋ฒ์ ์์ฒญํ ์ ์์ต๋๋ค. HTTP ์๋ฒ ์์ฒด๋ ํด๋ผ์ด์ธํธ์์ ํต์ ์ ์์ํ ์ ์์ต๋๋ค. ๊ฐ๋จํ ํด๊ฒฐ์ฑ ์ ํ์ด๋จธ๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ๋ฅผ ํด๋งํ๋ ๊ฒ์ด์ง๋ง ์ด๋ก ์ธํด ์๋ฒ์ ์ถ๊ฐ ๋ก๋๊ฐ ๋ฐ์ํ๊ณ ํ๊ท TimerInterval/2์ ์ถ๊ฐ ์ง์ฐ์ด ๋ฐ์ํฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Long Polling์ด๋ผ๋ ํธ๋ฆญ์ด ๋ฐ๋ช ๋์์ต๋๋ค. ์ ํ ์๊ฐ์ด ๋ง๋ฃ๋๊ฑฐ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๋๊น์ง ์๋ฒ์ ๋ณด๊ด๋ฉ๋๋ค. ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์ฒ๋ฆฌ๋๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ฒญ์ด ๋ค์ ์ ์ก๋ฉ๋๋ค.
while(!eventOccures && !timeoutExceeded) {
CheckTimout();
CheckEvent();
Thread.Sleep(1);
}
๊ทธ๋ฌ๋ ๊ทธ๋ฌํ ์๋ฃจ์ ์ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ํด๋ผ์ด์ธํธ ์๊ฐ ์ฆ๊ฐํ์๋ง์ ๋์ฐํ ๊ฒ์ผ๋ก ํ๋ช ๋ ๊ฒ์ ๋๋ค. ์๋ํ๋ฉด... ์ด๋ฌํ ๊ฐ ํด๋ผ์ด์ธํธ๋ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ ์ฒด ์ค๋ ๋๋ฅผ ์ฐจ์งํฉ๋๋ค. ์, ๊ทธ๋ฆฌ๊ณ ์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ๋ ๋ ์ถ๊ฐ๋ก 1ms์ ์ง์ฐ์ด ๋ฐ์ํฉ๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ด๋ ์ค์ํ์ง ์์ง๋ง ์ํํธ์จ์ด๋ฅผ ๊ฐ๋ฅํ ๊ฒ๋ณด๋ค ๋ ๋์๊ฒ ๋ง๋๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? 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);
}
}
์ด ์ฝ๋๋ ํ๋ก๋์ ์ค๋น๊ฐ ๋์ด ์์ง ์์ผ๋ฉฐ ๋จ์ง ๋ฐ๋ชจ์ผ ๋ฟ์ ๋๋ค. ์ค์ ์ฌ๋ก์์ ์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ต์ํ ์๋ฌด๋ ์์ํ์ง ์๋ ์๊ฐ์ ๋ฉ์์ง๊ฐ ๋์ฐฉํ๋ ์ํฉ์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ AsseptMessageAsync ๋ฉ์๋๋ ์ด๋ฏธ ์๋ฃ๋ ์์ ์ ๋ฐํํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ผ๋ฉด ValueTask ์ฌ์ฉ์ ๊ณ ๋ คํด ๋ณผ ์ ์์ต๋๋ค.
๋ฉ์์ง์ ๋ํ ์์ฒญ์ ๋ฐ์ผ๋ฉด TaskCompletionSource๋ฅผ ์์ฑํ์ฌ ์ฌ์ ์ ๋ฐฐ์นํ ๋ค์ ๋จผ์ ์ด๋ค ์ผ์ด ์ผ์ด๋ ์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ์ง์ ๋ ์๊ฐ ๊ฐ๊ฒฉ์ด ๋ง๋ฃ๋๊ฑฐ๋ ๋ฉ์์ง๊ฐ ์์ ๋ฉ๋๋ค.
ValueTask: ์ ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ
ํญ๋ณต ๋ฐํ ์ฐ์ฐ์์ ๊ฐ์ async/await ์ฐ์ฐ์๋ ๋ฉ์๋์์ ์ํ ์์คํ ์ ์์ฑํ๋ฉฐ ์ด๋ ๊ฑฐ์ ํญ์ ์ค์ํ์ง ์์ง๋ง ๋๋ฌผ๊ฒ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๋ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. ์ด ๊ฒฝ์ฐ๋ ์ ๋ง ์์ฃผ ํธ์ถ๋๋ ๋ฉ์๋์ผ ์ ์๋๋ฐ, ์ด๋น ์๋ง, ์์ญ๋ง ๊ฑด์ ํธ์ถ์ ์ด์ผ๊ธฐํ๊ณ ์๋ ์ ์ ๋๋ค. ์ด๋ฌํ ๋ฉ์๋๊ฐ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋ชจ๋ Wait ๋ฉ์๋๋ฅผ ์ฐํํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ผ๋ก ์์ฑ๋ ๊ฒฝ์ฐ .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);
}
์ค์ ๋ก ์ด ๊ฒฝ์ฐ ์ต์ ์ ์๋ฃจ์ ์ ํซ ํจ์ค๋ฅผ ์ต์ ํํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ๋ถํ์ํ ํ ๋น ๋ฐ 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));
}
์ด ์ฝ๋ ๋ถ๋ถ์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์บ์์ ๊ฐ์ด ์์ผ๋ฉด ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์ค์ ์์ ์ด ์๋ฏธ ์๋ ์์ ์ผ๋ก ๋ํ๋ฉ๋๋ค. ํธ์ถ ์ฝ๋๋ ์ด ์ฝ๋๊ฐ ์คํ๋ ๊ฒฝ๋ก๋ฅผ ์ ๊ฒฝ ์ฐ์ง ์์ต๋๋ค. C# ๊ตฌ๋ฌธ ๊ด์ ์์ ValueTask๋ ์ด ๊ฒฝ์ฐ ์ผ๋ฐ Task์ ๋์ผํ๊ฒ ๋์ํฉ๋๋ค.
TaskSchedulers: ์์ ์์ ์ ๋ต ๊ด๋ฆฌ
๋ค์์ผ๋ก ๊ณ ๋ คํ๊ณ ์ถ์ API๋ ํด๋์ค์ ๋๋ค. ์์ ์ค์ผ์ค๋ฌ ๊ทธ๋ฆฌ๊ณ ๊ทธ ํ์์ํ. ์์์ TPL์๋ ์ค๋ ๋ ์ ์ฒด์ ์์ ์ ๋ฐฐํฌํ๊ธฐ ์ํ ์ ๋ต์ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ด ์๋ค๊ณ ์ด๋ฏธ ์ธ๊ธํ์ต๋๋ค. ์ด๋ฌํ ์ ๋ต์ TaskScheduler ํด๋์ค์ ์์์ ์ ์๋ฉ๋๋ค. ํ์ํ ๊ฑฐ์ ๋ชจ๋ ์ ๋ต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ฐพ์ ์ ์์ต๋๋ค. ๋ณ๋ ฌ ํ์ฅ ์ถ๊ฐ ๊ธฐ๋ฅ, Microsoft์์ ๊ฐ๋ฐํ์ง๋ง .NET์ ์ผ๋ถ๋ ์๋์ง๋ง Nuget ํจํค์ง๋ก ์ ๊ณต๋ฉ๋๋ค. ๊ทธ ์ค ์ผ๋ถ๋ฅผ ๊ฐ๋จํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
- CurrentThreadTaskScheduler โ ํ์ฌ ์ค๋ ๋์์ ์์ ์ ์คํํฉ๋๋ค.
- LimitedConcurrencyLevelTaskScheduler โ ์์ฑ์์์ ํ์ฉ๋๋ ๋งค๊ฐ๋ณ์ N์ผ๋ก ๋์์ ์คํ๋๋ ์์ ์๋ฅผ ์ ํํฉ๋๋ค.
- OrderedTaskScheduler โ LimitedConcurrencyLevelTaskScheduler(1)๋ก ์ ์๋๋ฏ๋ก ์์ ์ด ์์ฐจ์ ์ผ๋ก ์คํ๋ฉ๋๋ค.
- ์ผํ์น๊ธฐTaskScheduler - ๊ตฌํ
์ผ์ ํ์น๋ ๊ฒ ์์ ๋ถ๋ฐฐ์ ์ ๊ทผํฉ๋๋ค. ๋ณธ์ง์ ์ผ๋ก ๋ณ๋์ ThreadPool์ ๋๋ค. .NET์์ ThreadPool์ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํด ํ๋์ ์ ์ ํด๋์ค์ด๋ฏ๋ก ํ๋ก๊ทธ๋จ์ ํ ๋ถ๋ถ์์ ์ค๋ฒ๋ก๋๋๊ฑฐ๋ ์๋ชป ์ฌ์ฉ๋๋ฉด ๋ค๋ฅธ ๋ถ๋ถ์์ ๋ถ์์ฉ์ด ๋ฐ์ํ ์ ์๋ค๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋์ฑ์ด, ๊ทธ๋ฌํ ๊ฒฐํจ์ ์์ธ์ ์ดํดํ๋ ๊ฒ์ ๊ทนํ ์ด๋ ต๋ค. ์ ๊ฒ. ThreadPool ์ฌ์ฉ์ด ๊ณต๊ฒฉ์ ์ด๊ณ ์์ธก ๋ถ๊ฐ๋ฅํ ์ ์๋ ํ๋ก๊ทธ๋จ ๋ถ๋ถ์์๋ ๋ณ๋์ WorkStealingTaskSchedulers๋ฅผ ์ฌ์ฉํด์ผ ํ ์๋ ์์ต๋๋ค. - ๋๊ธฐ ์ค์ธ ์์ ์ค์ผ์ค๋ฌ โ ์ฐ์ ์์ ๋๊ธฐ์ด ๊ท์น์ ๋ฐ๋ผ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
- ThreadPerTask์ค์ผ์ค๋ฌ โ ์คํ๋๋ ๊ฐ ์์ ์ ๋ํด ๋ณ๋์ ์ค๋ ๋๋ฅผ ์์ฑํฉ๋๋ค. ์๋ฃํ๋ ๋ฐ ์์ธกํ ์ ์์ ์ ๋๋ก ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ์์ ์ ์ ์ฉํ ์ ์์ต๋๋ค.
์์ธํ๊ฒ ์ ๋์์์ด์
์์ ๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ๊ฒ์ ํธ๋ฆฌํ๊ฒ ๋๋ฒ๊น ํ๊ธฐ ์ํด Visual Studio์๋ ์์ ์ฐฝ์ด ์์ต๋๋ค. ์ด ์ฐฝ์์ ์์ ์ ํ์ฌ ์ํ๋ฅผ ํ์ธํ๊ณ ํ์ฌ ์คํ ์ค์ธ ์ฝ๋ ์ค๋ก ์ด๋ํ ์ ์์ต๋๋ค.
PLinq ๋ฐ Parallel ํด๋์ค
Tasks ๋ฐ ์ด์ ๋ํด ์ธ๊ธ๋ ๋ชจ๋ ๊ฒ ์ธ์๋ .NET์๋ PLinq(Linq2Parallel) ๋ฐ Parallel ํด๋์ค๋ผ๋ ๋ ๊ฐ์ง ํฅ๋ฏธ๋ก์ด ๋๊ตฌ๊ฐ ๋ ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ ์ฌ๋ฌ ์ค๋ ๋์์ ๋ชจ๋ Linq ์์
์ ๋ณ๋ ฌ ์คํ์ ์ฝ์ํฉ๋๋ค. ์ค๋ ๋ ์๋ WithDegreeOfParallelism ํ์ฅ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ํ๊น๊ฒ๋ ๊ธฐ๋ณธ ๋ชจ๋์ PLinq์๋ ์๋นํ ์๋ ํฅ์์ ์ ๊ณตํ ๋งํผ ๋ฐ์ดํฐ ์์ค ๋ด๋ถ์ ๋ํ ์ ๋ณด๊ฐ ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๋ฐ๋ฉด์ ์๋ ๋น์ฉ์ ๋งค์ฐ ๋ฎ์ต๋๋ค. ๋จผ์ AsParallel ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋ฉ๋๋ค. Linq ๋ฉ์๋ ์ฒด์ธ์ ์คํํ๊ณ ์ฑ๋ฅ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค. ๋ํ ํํฐ์
๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ์์ค์ ํน์ฑ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ PLinq์ ์ ๋ฌํ ์๋ ์์ต๋๋ค. ๋ ์ฝ์ด๋ณด์ค ์ ์์ต๋๋ค
Parallel ์ ์ ํด๋์ค๋ Foreach ์ปฌ๋ ์ ์ ๋ณ๋ ฌ๋ก ๋ฐ๋ณตํ๊ณ , For ๋ฃจํ๋ฅผ ์คํํ๊ณ , ๋ณ๋ ฌ Invoke์์ ์ฌ๋ฌ ๋๋ฆฌ์๋ฅผ ์คํํ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ณ์ฐ์ด ์๋ฃ๋ ๋๊น์ง ํ์ฌ ์ค๋ ๋์ ์คํ์ด ์ค์ง๋ฉ๋๋ค. ParallelOptions๋ฅผ ๋ง์ง๋ง ์ธ์๋ก ์ ๋ฌํ์ฌ ์ค๋ ๋ ์๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ต์ ์ ์ฌ์ฉํ์ฌ TaskScheduler ๋ฐ CancellationToken์ ์ง์ ํ ์๋ ์์ต๋๋ค.
์กฐ์ฌ ๊ฒฐ๊ณผ
๋ณด๊ณ ์ ์๋ฃ์ ์ดํ ์์ ํ๋ฉด์ ์์งํ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์ด ๊ธ์ ์ฐ๊ธฐ ์์ํ์ ๋, ์ด๋ ๊ฒ ๋ง์ ๋ด์ฉ์ด ์์ ๊ฒ์ด๋ผ๊ณ ๋ ์์ํ์ง ๋ชปํ์ต๋๋ค. ์ด์ ๋ด๊ฐ ์ด ๊ธ์ ์ฐ๊ณ ์๋ ํ ์คํธ ํธ์ง๊ธฐ๊ฐ 15ํ์ด์ง๊ฐ ์ฌ๋ผ์ก๋ค๊ณ ๋น๋ํ๋ฉด์ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์์ฝํ๊ฒ ์ต๋๋ค. ๋ค๋ฅธ ํธ๋ฆญ, API, ์๊ฐ์ ๋๊ตฌ ๋ฐ ํจ์ ์ ๋ค์ ๊ธฐ์ฌ์์ ๋ค๋ฃจ๊ฒ ์ต๋๋ค.
๊ฒฐ๋ก :
- ์ต์ PC์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ค๋ ๋, ๋น๋๊ธฐ ๋ฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋๊ตฌ๋ฅผ ์์์ผ ํฉ๋๋ค.
- .NET์๋ ์ด๋ฌํ ๋ชฉ์ ์ ์ํ ๋ค์ํ ๋๊ตฌ๊ฐ ์์ต๋๋ค.
- ๋ชจ๋ API๊ฐ ํ๊บผ๋ฒ์ ๋ํ๋๋ ๊ฒ์ ์๋๊ธฐ ๋๋ฌธ์ ๋ ๊ฑฐ์ API๋ฅผ ์ข ์ข ์ฐพ์ ์ ์์ง๋ง, ๋ง์ ๋ ธ๋ ฅ์ ๋ค์ด์ง ์๊ณ ๋ ์ค๋๋ API๋ฅผ ๋ณํํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
- .NET์์ ์ค๋ ๋ ์์ ์ Thread ๋ฐ ThreadPool ํด๋์ค๋ก ํํ๋ฉ๋๋ค.
- Thread.Abort, Thread.Interrupt ๋ฐ Win32 API TerminateThread ๋ฉ์๋๋ ์ํํ๋ฏ๋ก ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋์ CancellationToken ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ต๋๋ค.
- ํ๋ฆ์ ๊ท์คํ ์์์ด๋ฉฐ ๊ณต๊ธ์ด ์ ํ๋์ด ์์ต๋๋ค. ์ค๋ ๋๊ฐ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋๋ผ ๋ฐ์ ์ํฉ์ ํผํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด TaskCompletionSource ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํธ๋ฆฌํฉ๋๋ค.
- ๋ณ๋ ฌ ์ฒ๋ฆฌ ๋ฐ ๋น๋๊ธฐ ์์ ์ ์ํ ๊ฐ์ฅ ๊ฐ๋ ฅํ๊ณ ์ง๋ณด๋ .NET ๋๊ตฌ๋ ์์ ์ ๋๋ค.
- C# async/await ์ฐ์ฐ์๋ ๋น์ฐจ๋จ ๋๊ธฐ ๊ฐ๋ ์ ๊ตฌํํฉ๋๋ค.
- TaskScheduler ํ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ ๋ ๊ฐ ์์ ๋ฐฐํฌ๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค.
- ValueTask ๊ตฌ์กฐ๋ ํซ ํจ์ค ๋ฐ ๋ฉ๋ชจ๋ฆฌ ํธ๋ํฝ์ ์ต์ ํํ๋ ๋ฐ ์ ์ฉํ ์ ์์ต๋๋ค.
- Visual Studio์ ์์ ๋ฐ ์ค๋ ๋ ์ฐฝ์ ๋ค์ค ์ค๋ ๋ ๋๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋๋ฒ๊น ํ๋ ๋ฐ ์ ์ฉํ ๋ง์ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
- PLinq๋ ๋ฉ์ง ๋๊ตฌ์ด์ง๋ง ๋ฐ์ดํฐ ์์ค์ ๋ํ ์ ๋ณด๊ฐ ์ถฉ๋ถํ์ง ์์ ์ ์์ง๋ง ํํฐ์ ๋ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
- ๊ณ์ ๋ ...
์ถ์ฒ : habr.com