HttpClient๋ ์ผ๋ถ ์ํฉ์์ ์๊ฐ ์ด๊ณผ ์ TaskCanceledException์ ๋ฐ์์ํต๋๋ค. ์ด๊ฒ์ ์๋ฒ๊ฐ ๊ณผ๋ถํ ์ํ์ผ ๋ ๋ฐ์ํฉ๋๋ค. ๊ธฐ๋ณธ ์๊ฐ ์ด๊ณผ๋ฅผ ๋๋ ค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์์ต๋๋ค. ๋ค์ MSDN ํฌ๋ผ ์ค๋ ๋๋ ๊ฒฝํํ ๋ฌธ์ ์ ๋ณธ์ง์ ํฌ์ฐฉํฉ๋๋ค. https://social.msdn.microsoft.com/Forums/en-US/d8d87789-0ac9-4294-84a0-91c9fa27e353/bug-in-httpclientgetasync-should-throw -webexception-not-taskcancelledexception?forum=netfxnetcom&prof=required
๊ฐ์ฌ ํด์
@awithy ์ด๋ค ๋ฒ์ ์ .NET Core๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๊น?
1.1
์ฌ๋ฐ๋ฅธ ๋์์ธ์ด๋ ์๋๋ , ์ค๊ณ์ OperationCanceledExceptions๋ ์๊ฐ ์ด๊ณผ์ ๋ํด throw๋ฉ๋๋ค(TaskCanceledException์ OperationCanceledException์).
์ฐธ์กฐ: @davidsh
์ฐ๋ฆฌ ํ์ ์ด๊ฒ์ด ์ง๊ด์ ์ด์ง ์๋ค๋ ๊ฒ์ ์์์ง๋ง ์ค๊ณ๋ ๋๋ก ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋ถํํ๋, ์ฐ๋ฆฌ๊ฐ ์ด๊ฒ์ ์ณค์ ๋ ์ฐ๋ฆฌ๋ ์ทจ์ ์์ค๋ฅผ ์ฐพ๋ ๋ฐ ์ฝ๊ฐ์ ์๊ฐ์ ๋ญ๋นํ์ต๋๋ค. ์ด ์๋๋ฆฌ์ค๋ฅผ ์์ ์ทจ์์ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฒ์ ๊ฝค ์ถํ ์ผ์ ๋๋ค(์ด๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ์ ์ง์ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ๋ง๋ค์์ต๋๋ค). ์ด๊ฒ๋ ์ทจ์๋ผ๋ ๊ฐ๋ ์ ๋จ์ฉํ ๊ฒ ๊ฐ๋ค.
๋น ๋ฅธ ์๋ต์ ๋ค์ ํ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์ค๊ณ์ + ์ง๋ 6๊ฐ์ ์ด์ ๋์ 2๋ช
์ ๊ณ ๊ฐ์ด ๋ถ๋ง์ ์ ๊ธฐํ ๊ฒ ๊ฐ์ต๋๋ค.
ํ์.
@karelz ๋ ์ด ์คํด์ ์์ง๊ฐ ์๋ ์์ธ์ ์ํฅ์ ๋ฐ๋ ๋ค๋ฅธ ๊ณ ๊ฐ์ผ๋ก ๋ฉ๋ชจ๋ฅผ ์ถ๊ฐํ๊ณ ์์ต๋๋ค. :)
์ ๋ณด๋ฅผ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์์ ๊ฒ์๋ฌผ์๋ ํฌํํด ์ฃผ์ธ์(๋ฌธ์ ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ ์ ์์). ๊ฐ์ฌํฉ๋๋ค!
์ฌ๋ฐ๋ฅธ ์ค๊ณ ์ฌ๋ถ์ ๊ด๊ณ์์ด ์ค๊ณ์ OperationCanceledExceptions๋ ์๊ฐ ์ด๊ณผ์ ๋ํด throw๋ฉ๋๋ค.
์ด๊ฒ์ ๋์ ๋์์ธ IMO์
๋๋ค. ์์ฒญ์ด ์ค์ ๋ก ์ทจ์๋์๋์ง(์ฆ, SendAsync
์ ์ ๋ฌ๋ ์ทจ์ ํ ํฐ์ด ์ทจ์๋์๋์ง) ๋๋ ์๊ฐ ์ด๊ณผ๊ฐ ๊ฒฝ๊ณผํ๋์ง ์ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ํ์์ ๊ฒฝ์ฐ ์ฌ์๋ํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ด์ง๋ง ์ ์์ ๊ฒฝ์ฐ์๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ์ ๋ฑ ๋ง๋ TimeoutException
๊ฐ ์์ต๋๋ค. ์ฌ์ฉํ์ง ์์ผ์๊ฒ ์ต๋๊น?
์, ์ด๊ฒ์ ๋ํ ์ฐ๋ฆฌ ํ์ ๋ฃจํ์ ๋น ๋จ๋ ธ์ต๋๋ค. ์ด๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ ์ฒด ์คํ ์ค๋ฒํ ๋ก ์ค๋ ๋๊ฐ ์์ต๋๋ค.
๋ฉฐ์น ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๊ฒ์ํ์ต๋๋ค. https://www.thomaslevesque.com/2018/02/25/better-timeout-handling-with-httpclient/
๊ต์ฅํฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
์ด์ ๊ด์ฌ์ด ๋ ์ปค์ง์ ๋ฐ๋ผ ์ฌ๊ฐ๋ฐฉ - StackOverflow ์ค๋ ๋๋ ์ด์ 69๊ฐ์ ์ฐฌ์ฑ์ ์ป์์ต๋๋ค.
cc @dotnet/ncl
์ด๋ค ์์์ด ์์ต๋๊น? ์ฌ์ ํ dotnet core 2.0์์ ๋ฐ์ํฉ๋๋ค.
2.1 ์ดํ์ ์ฃผ์ ๋ฌธ์ ๋ชฉ๋ก์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ 2.0/2.1์์๋ ์์ ๋์ง ์์ต๋๋ค.
์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ ๋ ์ํํ ์์ ์๋ ๋ช ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค.
TaskCanceledException
TimeoutException
๋ฅผ ๋์ง๋๋ค.TimeoutException
$#$์ ๊ฐ์ ๋ด๋ถ ์์ธ์ ํจ๊ป TaskCanceledException
๋์ง๊ธฐInnerException
( TimeoutException.InnerException
๋ก)๋ฅผ ๋ณด์กดํ๋ฉด์ ์๋์ TaskCanceledException
์คํ์ ๋ฒ๋ฆฌ๊ณ ์ ์คํ์ ๋์ ธ๋ ๊ด์ฐฎ์ต๋๊น? ์๋๋ฉด ์๋ TaskCanceledException
๋ฅผ ๋ณด์กดํ๊ณ ํฌ์ฅํด์ผ ํฉ๋๊น?TaskCanceledException
๋ฅผ ๋์ง๋๋ค.์๋ TaskCanceledException
์ ์๋ ์คํ์ ๋ฒ๋ฆฌ๊ณ ์ต์
[2]์ ๊ธฐ๋๊ณ ์์ต๋๋ค.
@stephentoub @davidsh ์๊ฐ์ด ์์ผ์ญ๋๊น?
BTW: ์๊ฐ ์ ํ์ ์ค์ ํ HttpClient.SendAsync
์์ ๋ณ๊ฒฝ ์ฌํญ์ ๋งค์ฐ ๊ฐ๋จํด์ผ ํฉ๋๋ค.
https://github.com/dotnet/corefx/blob/30fb78875148665b98748ede3013641734d9bf5c/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L433 -L461
์ต์์ ์์ธ๋ ํญ์ HttpRequestException์ด์ด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด HttpClient์ ํ์ค API ๋ชจ๋ธ์ ๋๋ค.
๊ทธ ์์์ ๋ด๋ถ ์์ธ๋ก "์๊ฐ ์ด๊ณผ"๋ ์๋ง๋ TimeoutException์ด์ด์ผ ํฉ๋๋ค. ์ฌ์ค, ์ด๊ฒ์ ๋ค๋ฅธ ๋ฌธ์ ์ ๊ฒฐํฉํ๋ค๋ฉด(WebExceptionStatus์ ์ ์ฌํ ์๋ก์ด ์ด๊ฑฐํ ์์ฑ์ ํฌํจํ๋๋ก HttpRequestion์ ์์ ํ๋ ๊ฒ๊ณผ ๊ด๋ จํ์ฌ) ๊ฐ๋ฐ์๋ ํด๋น ์ด๊ฑฐํ์ ํ์ธํ๊ธฐ๋ง ํ๋ฉด ๋๋ฉฐ ๋ด๋ถ ์์ธ๋ฅผ ์ ํ ๊ฒ์ฌํ ํ์๊ฐ ์์ต๋๋ค.
์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ต์ 1)์ด์ง๋ง HttpClient API์ ์ต์์ ์์ธ๊ฐ ํญ์ HttpRequestException์ด๋ผ๋ ํ์ฌ ์ฑ ํธํ API ๋ชจ๋ธ์ ๊ณ์ ์ ์งํฉ๋๋ค.
์ฐธ๊ณ : ๋ค์๊ณผ ๊ฐ์ Stream API์์ HTTP ์๋ต ์คํธ๋ฆผ์ ์ง์ ์ฝ์ ๋ "์๊ฐ ์ด๊ณผ"๊ฐ ๋ฐ์ํฉ๋๋ค.
```c#
var ํด๋ผ์ด์ธํธ = ์๋ก์ด HttpClient();
์คํธ๋ฆผ responseStream = client.GetStreamAsync(url)๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
int bytesRead = responseStream.ReadAsync(๋ฒํผ, 0, ๋ฒํผ ๊ธธ์ด)๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
```
๊ณ์ํด์ System.IO.IOException ๋ฑ์ ์ต์์ ์์ธ๋ก ๋์ ธ์ผ ํฉ๋๋ค(์ค์ ๋ก ์ด๊ฒ์ ๋ํด SocketsHttpHandler์ ๋ช ๊ฐ์ง ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค).
@davidsh ๋ช
์์ ์ฌ์ฉ์ ์ทจ์๊ฐ ์๋ ๊ฒฝ์ฐ์๋ HttpRequestException
๋ฅผ ๋์ง๋ผ๊ณ ์ ์ํฉ๋๊น? ๊ทธ๋ค์ ์ค๋ TaskCanceledException
๋ฅผ ๋์ก๊ณ ๊ด์ฐฎ์ ๋ณด์
๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ฐ๊พธ๊ณ ์ถ์ ๊ฒ์ธ์ง ํ์คํ์ง ์์ต๋๋ค ...
ํด๋ผ์ด์ธํธ ์ธก ์๊ฐ ์ด๊ณผ๋ฅผ $#$ TaskCanceledException
HttpRequestException
๋ก ๋
ธ์ถํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
@davidsh ๋ช ์์ ์ฌ์ฉ์ ์ทจ์๊ฐ ์๋ ๊ฒฝ์ฐ์๋ HttpRequestException์ throwํ ๊ฒ์ ์ ์ํ๊ณ ์์ต๋๊น? ๊ทธ๊ฒ๋ค์ ์ค๋ TaskCanceledException์ ๋์ก๊ณ ๊ด์ฐฎ์ ๋ณด์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ฐ๊พธ๊ณ ์ถ์ ๊ฒ์ธ์ง ํ์คํ์ง ์์ต๋๋ค ...
์ด ์ง๋ฌธ์ ๋ตํ๊ธฐ ์ ์ ์ ํํ ํ์ฌ ๋์์ ํ์ธํ๊ธฐ ์ํด .NET Framework๋ฅผ ํฌํจํ ์คํ์ ๋ค์ํ ๋์์ ํ ์คํธํด์ผ ํฉ๋๋ค.
๋ํ ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ผ๋ถ ์คํ์์ OperationCanceledException์ ๋ด๋ถ ์์ธ์ ํจ๊ป HttpRequestException์ throwํฉ๋๋ค. TaskCanceledException์ OperationCanceledException์ ํ์ ์ ํ์ ๋๋ค.
๋ช ์์ ์ฌ์ฉ์ ์ทจ์๊ฐ ์๋ ๊ฒฝ์ฐ
๋ํ "๋ช ์์ "์ด ๋ฌด์์ธ์ง์ ๋ํ ๋ช ํํ ์ ์๊ฐ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, HttpClient.Timeout ์์ฑ์ "๋ช ์์ "์ผ๋ก ์ค์ ํ๊ณ ์์ต๋๊น? ๋๋ ์ฐ๋ฆฌ๊ฐ ์๋์ค๋ผ๊ณ ๋งํ๋ ๊ฒ ๊ฐ์์. CancellationTokenSource ๊ฐ์ฒด์์ .Cancel()์ ํธ์ถํ๋ ๊ฒ์ ์ด๋ป์ต๋๊น(CancellationToken ๊ฐ์ฒด์ ์ ๋ฌ๋ ๊ฒ์ ์ํฅ์ ๋ฏธ์นจ)? "๋ช ์์ "์ธ๊ฐ์? ์ฐ๋ฆฌ๊ฐ ์๊ฐํ ์ ์๋ ๋ค๋ฅธ ์๊ฐ ์์ ๊ฒ์ ๋๋ค.
.NET Framework๋ HttpClient.Timeout
๋ฅผ ์ค์ ํ ๋๋ TaskCanceledException์ ๋ฐ์์ํต๋๋ค.
ํด๋ผ์ด์ธํธ ์ทจ์์ ๊ตฌํ ์ทจ์๋ฅผ ๊ตฌ๋ถํ ์ ์์ผ๋ฉด ๋ ๋ค ์ ํํ์ญ์์ค. ํด๋ผ์ด์ธํธ ํ ํฐ์ ์ฌ์ฉํ๊ธฐ ์ ์ ํ์๋ ํ ํฐ์ ๋ง๋์ธ์.
```c#
var ํด๋ผ์ด์ธํธ ํ ํฐ = ....
var innerTokenSource = CancellationTokenSource.CreateLinkedTokenSource(clientToken);
If at some point you catch **OperationCancelledException**:
```c#
try
{
//invocation with innerToken
}
catch(OperationCancelledException oce)
{
if(clientToken.IsCancellationRequested)
throw; //as is, it is client initiated and in higher priority
if(innerToken.IsCancellationRequested)
//wrap it in HttpException, TimeoutException, whatever, wrap it in another linked token until you process all cases.
}
๊ธฐ๋ณธ์ ์ผ๋ก ์ทจ์๋ฅผ ์ ๋ฐํ ํ ํฐ์ ์ฐพ์ ๋๊น์ง ํด๋ผ์ด์ธํธ ํ ํฐ์์ ๊ฐ์ฅ ๊น์ ๋ ์ด์ด๊น์ง ๊ฐ๋ฅํ ๋ชจ๋ ๋ ์ด์ด๋ฅผ ํํฐ๋งํฉ๋๋ค.
2.2 ๋๋ 3.0์ ๋ง๋๋ ๊ฒ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น? @karelz @davidsh , cc @NickCraver . ๋๋ TimeoutException์ ๋์ง๋ ์ต์ 1) ๋๋ HttpRequestException์์ ํ์๋ ์๋ก์ด HttpTimeoutException์ ๋์ง๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๊ฐ์ฌ ํด์!
2.2 ๋๋ 3.0์ ๋ง๋๋ ๊ฒ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น?
2.2 ์น๊ณ ๋ ๋๋ฌด ๋ฆ์ด์ ์ง๋์ฃผ์ ์ถ์ ๋์์ด์ ;)
2.2 ์น๊ณ ๋ ๋๋ฌด ๋ฆ์ด์ ์ง๋์ฃผ์ ์ถ์ ๋์์ด์ ;)
์, ์ฌ๋ ์๊ฐ์ ์ด๋ ๊ฒ ๋๋๊ตฐ์ ;)
์ฝ๊ฐ ๋ฐ๋ณด ๊ฐ์ง๋ง ๋ด๊ฐ ์ฐพ์ ๊ฐ์ฅ ๊ฐ๋จํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ OperationCanceledException์ ๋ํ catch ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ค์ฒฉํ ๋ค์ IsCancellationRequested ๊ฐ์ ํ๊ฐํ์ฌ ์ทจ์ ํ ํฐ์ด ์๊ฐ ์ด๊ณผ ๋๋ ์ค์ ์ธ์ ์ค๋จ์ ๊ฒฐ๊ณผ์ธ์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ฒ์ ๋๋ค. ๋ถ๋ช ํ API ํธ์ถ์ ์ํํ๋ ๋ ผ๋ฆฌ๋ ๋น์ฆ๋์ค ๋ ผ๋ฆฌ ๋๋ ์๋น์ค ๊ณ์ธต์ ์์ ์ ์์ง๋ง ๋จ์์ฑ์ ์ํด ์์ ๋ฅผ ํตํฉํ์ต๋๋ค.
````์คํ
[HttpGet]
๊ณต๊ฐ ๋น๋๊ธฐ ์์
{
๋
ธ๋ ฅํ๋ค
{
// ์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์ปจํธ๋กค๋ฌ ์์ฒด๊ฐ ์๋ ๋น์ฆ๋์ค ๋ก์ง ๋๋ ์๋น์ค ๊ณ์ธต์์ ์ํ๋์ง๋ง ๋จ์์ฑ์ ์ํด ์ฌ๊ธฐ์์ ์์ ์ ์ค๋ช
ํฉ๋๋ค.
๋
ธ๋ ฅํ๋ค
{
//HttpClient ์ธ์คํด์ค์ HttpClientFactory ์ฌ์ฉ
var httpClient = _httpClientFactory.CreateClient();
//Set an absurd timeout to illustrate the point
httpClient.Timeout = new TimeSpan(0, 0, 0, 0, 1);
//Perform call that requires special timeout logic
var httpResponse = await httpClient.GetAsync("https://someurl.com/api/long/running");
//... (if GetAsync doesn't fail, handle the response as desired)
}
catch (OperationCanceledException innerOperationCanceled)
{
//If a canceled token exception occurs due to a timeout, "IsCancellationRequested" should be false
if (cancellationToken.IsCancellationRequested)
{
//Bubble exception to global handler
throw innerOperationCanceled;
}
else
{
//... (perform timeout logic here)
}
}
}
catch (OperationCanceledException operationCanceledEx)
{
_logger.LogWarning(operationCanceledEx, "Request was aborted by the end user.");
return new StatusCodeResult(499);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unexepcted error occured.");
return new StatusCodeResult(500);
}
}
````
์ด ์๋๋ฆฌ์ค๋ฅผ ๋ณด๋ค ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ค๋ฅธ ๊ธฐ์ฌ๋ฅผ ๋ณด์์ง๋ง ๋ชจ๋ ํ์ดํ๋ผ์ธ ๋ฑ์ ํํค์ณ์ผ ํฉ๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ด ์๋ฒฝํ์ง ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ๋ฏธ๋์ ์ค์ ์๊ฐ ์ด๊ณผ ์์ธ์ ๋ํ ๋ ๋์ ์ง์์ด ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ํ์ด ์ฃผ๋ค.
http ํด๋ผ์ด์ธํธ๋ก ์์ ํ๋ ๊ฒ์ ์์ ํ ์ต์ ์ ๋๋ค. HttpClient๋ฅผ ์ญ์ ํ๊ณ ์ฒ์๋ถํฐ ๋ค์ ์์ํด์ผ ํฉ๋๋ค.
์ฝ๊ฐ ๋ฐ๋ณด ๊ฐ์ง๋ง ๋ด๊ฐ ์ฐพ์ ๊ฐ์ฅ ๊ฐ๋จํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ OperationCanceledException์ ๋ํ catch ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ค์ฒฉํ ๋ค์ IsCancellationRequested ๊ฐ์ ํ๊ฐํ์ฌ ์ทจ์ ํ ํฐ์ด ์๊ฐ ์ด๊ณผ ๋๋ ์ค์ ์ธ์ ์ค๋จ์ ๊ฒฐ๊ณผ์ธ์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ฒ์ ๋๋ค. ๋ถ๋ช ํ API ํธ์ถ์ ์ํํ๋ ๋ ผ๋ฆฌ๋ ๋น์ฆ๋์ค ๋ ผ๋ฆฌ ๋๋ ์๋น์ค ๊ณ์ธต์ ์์ ์ ์์ง๋ง ๋จ์์ฑ์ ์ํด ์์ ๋ฅผ ํตํฉํ์ต๋๋ค.
[HttpGet] public async Task<IActionResult> Index(CancellationToken cancellationToken) { try { //This would normally be done in a business logic or service layer rather than in the controller itself but I'm illustrating the point here for simplicity sake try { //Using HttpClientFactory for HttpClient instances var httpClient = _httpClientFactory.CreateClient(); //Set an absurd timeout to illustrate the point httpClient.Timeout = new TimeSpan(0, 0, 0, 0, 1); //Perform call that requires special timeout logic var httpResponse = await httpClient.GetAsync("https://someurl.com/api/long/running"); //... (if GetAsync doesn't fail, handle the response as desired) } catch (OperationCanceledException innerOperationCanceled) { //If a canceled token exception occurs due to a timeout, "IsCancellationRequested" should be false if (cancellationToken.IsCancellationRequested) { //Bubble exception to global handler throw innerOperationCanceled; } else { //... (perform timeout logic here) } } } catch (OperationCanceledException operationCanceledEx) { _logger.LogWarning(operationCanceledEx, "Request was aborted by the end user."); return new StatusCodeResult(499); } catch (Exception ex) { _logger.LogError(ex, "An unexepcted error occured."); return new StatusCodeResult(500); } }
์ด ์๋๋ฆฌ์ค๋ฅผ ๋ณด๋ค ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ค๋ฅธ ๊ธฐ์ฌ๋ฅผ ๋ณด์์ง๋ง ๋ชจ๋ ํ์ดํ๋ผ์ธ ๋ฑ์ ํํค์ณ์ผ ํฉ๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ด ์๋ฒฝํ์ง ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ๋ฏธ๋์ ์ค์ ์๊ฐ ์ด๊ณผ ์์ธ์ ๋ํ ๋ ๋์ ์ง์์ด ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ํ์ด ์ฃผ๋ค.
์ฐ๋ฆฌ๊ฐ ์ด ๋์ฐํ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒ์ ์ ๋์ ์ผ๋ก ๊ณจ์น ์ํ ์ผ์ ๋๋ค. HttpClient๋ Microsoft์์ ๋ง๋ ๊ฐ์ฅ ๋์ถ๋๋ ์ถ์ํ์ ๋๋ค.
์๊ฐ ์ด๊ณผ์ ๋ํ ๋ณด๋ค ๊ตฌ์ฒด์ ์ธ ์์ธ ์ ๋ณด๋ฅผ ํฌํจํ์ง ์๋ ๊ฒ์ด ๊ทผ์์์ ์ผ๋ก ๋ณด์ธ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ์ฌ๋๋ค์ด ์ค์ ์๊ฐ ์ด๊ณผ๋ฅผ ์ทจ์๋ ํ ํฐ ์์ธ์ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ธฐ๋ฅผ ์ํ๋ ์์ฃผ ๊ธฐ๋ณธ์ ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
http ํด๋ผ์ด์ธํธ๋ก ์์ ํ๋ ๊ฒ์ ์์ ํ ์ต์ ์ ๋๋ค. HttpClient๋ฅผ ์ญ์ ํ๊ณ ์ฒ์๋ถํฐ ๋ค์ ์์ํด์ผ ํฉ๋๋ค.\
๊ทธ๊ฒ์ ๋ณ๋ก ๋์์ด ๋์ง ์๊ฑฐ๋ ๊ฑด์ค์ ์ธ ํผ๋๋ฐฑ @dotnetchris ์ ๋๋ค. ๊ณ ๊ฐ๊ณผ MSFT ์ง์์ ๋ชจ๋ ๋ ๋์ ๊ฒ์ ๋ง๋ค๊ธฐ ์ํด ์ฌ๊ธฐ ์์ผ๋ฉฐ @karelz ์ ๊ฐ์ ์ฌ๋๋ค์ ์ฌ์ ํ โโ๊ณ ๊ฐ ํผ๋๋ฐฑ์ ๊ท๋ฅผ ๊ธฐ์ธ์ด๊ณ ๊ฐ์ ํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค. ๊ทธ๋ค์ด ๊ณต๊ฐ์ ์ผ๋ก ๊ฐ๋ฐ์ ํด์ผ ํ๋ค๋ ์๊ตฌ ์ฌํญ์ ์์ผ๋ฉฐ, ๊ทธ๋ค์ ์ ์๋ฅผ ๋ถ์ ์ ์ผ๋ก ๋ถํ์ฐ์ง ์๋๋ก ํฉ์๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๊ทธ๋ค์ด ๊ณต์ ๊ฐ์ง๊ณ ์ง์ ๊ฐ๊ธฐ๋ก ๊ฒฐ์ ํ ์ ์์ผ๋ฉฐ, ์ด๋ ์ปค๋ฎค๋ํฐ์ ๋ ๋์ ๊ฒ์ ๋๋ค. ๊ฐ์ฌ ํด์! :)
์์ ๋์์ ๊ฐ์ง HttpClient2(์์ ์ด๋ฆ)๋ฅผ ๋ง๋ค๊ณ ์ค๋ช ์์์ "HttpClient๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. HttpClient2๋ฅผ ์ฌ์ฉํ์ญ์์ค"๋ผ๊ณ ์๋ฆฌ๊ณ ๋ ์ฌ์ด์ ์ฐจ์ด์ ์ ์ค๋ช ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด .NetFramework์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์ฝ์ ๋์ง ์์ต๋๋ค.
HttpClient๋ ์์ธ ๋ฐ์์ ๊ธฐ๋ฐ์ผ๋ก ํด์๋ ์ ๋ฉ๋๋ค. ์ธํฐ๋ท ํธ์คํธ๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ์์ธ๊ฐ ์๋๋๋ค. ์ฃผ์์ ๋ฌดํํ ์์ด์ ๊ฐ์ํ ๋ ์ค์ ๋ก ์์๋๋ ๊ฒ์ ์์ธ์ ์ธ ๊ฒฝ์ฐ๊ฐ ์๋ํ๋ ๊ฒ์ ๋๋ค.
๋๋ ์ฌ์ง์ด 3๋ ์ ์ HttpClient๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ง๋ ๋์์ง์ ๋ํด ๋ธ๋ก๊ทธ์ ๊ธ์ ๋จ๊ฒผ์ต๋๋ค. https://dotnetchris.wordpress.com/2015/12/11/working-with-httpclient-is-absurd/
์ด๊ฒ์ ๋์ ๋๊ฒ ๋์ ๋์์ธ์ ๋๋ค.
Microsoft์ ๋๊ตฐ๊ฐ๊ฐ HttpClient๋ฅผ ์ฌ์ฉํ ์ ์ด ์์ต๋๊น? ํ์คํ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ด ๋์ฐํ API ํ๋ฉด ๋๋จธ์๋ ๊ทธ๊ฒ์ ๊ตฌ์ฑ๊ณผ ์ค๋ ๋ฉ์ ๊ดํ ์จ๊ฐ ์ข ๋ฅ์ ์ถ์์ ์ธ ๋์๊ฐ ์์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ๊ตฌ์ ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด ๋ฏฟ์ ์ ์๊ณ ์ค์ง ์์ฃผ ์๋ก์ด ๊ฒ์ด ์คํ ๊ฐ๋ฅํ ์๋ฃจ์ ์ด๋ผ๋ ๊ฒ์ ๋ฏฟ์ ์ ์์ต๋๋ค. HttpClient2, HttpClientSlim์ ๊ด์ฐฎ์ต๋๋ค.
Http ์ก์ธ์ค๋ ์์ธ๋ฅผ throwํ์ง ์์์ผ ํฉ๋๋ค. ํญ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํด์ผ ํ๋ฉฐ ๊ฒฐ๊ณผ๋ ์๋ฃ, ์๊ฐ ์ด๊ณผ, http ์๋ต์ ๊ฒ์ฌํ ์ ์์ด์ผ ํฉ๋๋ค. throw๊ฐ ํ์ฉ๋์ด์ผ ํ๋ ์ ์ผํ ์ด์ ๋ EnsureSuccess()
๋ฅผ ํธ์ถํ๋ฉด ์ธ๊ณ์์ ์์ธ๋ฅผ throwํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ์ธํฐ๋ท์ ์์ ํ ์ ์์ ์ธ ๋์์ ๋ํ ์ ์ด ํ๋ฆ ์ฒ๋ฆฌ๊ฐ ์์ด์ผ ํฉ๋๋ค. ํธ์คํธ ๊ฐ๋, ํธ์คํธ ๊ฐ๋ ์ค์ง, ํธ์คํธ ์๊ฐ ์ด๊ณผ. ๊ทธ ์ค ์ด๋ ๊ฒ๋ ์์ธ์ ์ด์ง ์์ต๋๋ค.
HttpClient๋ ์์ธ ๋ฐ์์ ๊ธฐ๋ฐ์ผ๋ก ํด์๋ ์ ๋ฉ๋๋ค. ์ธํฐ๋ท ํธ์คํธ๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ์์ธ๊ฐ ์๋๋๋ค. ์ฃผ์์ ๋ฌดํํ ์์ด์ ๊ฐ์ํ ๋ ์ค์ ๋ก ์์๋๋ ๊ฒ์ ์์ธ์ ์ธ ๊ฒฝ์ฐ๊ฐ ์๋ํ๋ ๊ฒ์ ๋๋ค.
@dotnetchris ์ด ์ฃผ์ ์ ๋ํด ๋ง์ ์ด์ ์ ๊ฐ๊ณ ๊ณ์ ๊ฒ ๊ฐ์ผ๋ ์๊ฐ์ ๋ด์ด HttpClient2์ ๋ํด ์ ์๋ ์ ์ฒด API๋ฅผ ์์ฑํ๊ณ ์ ๋ฌธ์ ๋ก ํ ๋ก ์ ์ํด ํ์ ์ ์ถํ๋ ๊ฒ์ด ์ด๋ป์ต๋๊น?
๋๋ ๋ ๊น์ ๊ธฐ์ ์์ค์์ HttpClient๋ฅผ ์ข๊ฑฐ๋ ๋์๊ฒ ๋ง๋๋ ํต์ฌ ์ฌํญ์ ๋ํด ์์ธํ ์์๋ณด์ง ์์์ผ๋ฏ๋ก @dotnetchris์ ์๊ฒฌ์ ์ถ๊ฐํ ๊ฒ์ด ์์ต๋๋ค. MS ๊ฐ๋ฐํ์ ๋นํํ๋ ๊ฒ์ ์ ์ ํ์ง ์๋ค๊ณ ์๊ฐํ์ง๋ง ์ฒ๋ฆฌํ๊ธฐ ๋งค์ฐ ๊ฐ๋จํด ๋ณด์ด๋ ์ํฉ์ ๋ํ ์๋ฃจ์ ์ ์ฐ๊ตฌํ๋ ๋ฐ ๋ช ์๊ฐ๊ณผ ๋ช ์๊ฐ์ ์๋นํ๋ ๊ฒ์ด ์ผ๋ง๋ ๋ต๋ตํ์ง ์ดํดํฉ๋๋ค. ํน์ ๊ฒฐ์ /๋ณ๊ฒฝ์ด ์ด๋ฃจ์ด์ง ์ด์ ๋ฅผ ์ดํดํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช๋๋ค๋ ๊ฒ์ MS์ ๋๊ตฐ๊ฐ๊ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋์์ ์ฌ์ ํ ์์ ์ ์๋ฃํ๊ณ ์ ๋ฌํ๊ธฐ๋ฅผ ๋ฐ๋ผ๋ ๊ฒ์ ๋๋ค.
์ ๊ฒฝ์ฐ์๋ ์ฌ์ฉ์ ์ญํ ์ ์ค์ ํ๊ธฐ ์ํด OAuth ํ๋ก์ธ์ค ์ค์ ํธ์ถํ๋ ์ธ๋ถ ์๋น์ค๊ฐ ์์ผ๋ฉฐ ํด๋น ํธ์ถ์ด ์ง์ ๋ ์๊ฐ ๋ฒ์ ๋ด์์ ์๊ฐ ์ด๊ณผ๋๋ฉด(๋ถํํ๊ฒ๋ ์ํ๋ ๊ฒ๋ณด๋ค ๋ ๋ง์ด ๋ฐ์ํจ) ๋ณด์กฐ ๋ฐฉ๋ฒ์ผ๋ก ๋๋๋ ค์ผ ํฉ๋๋ค. .
์ค์ ๋ก ๋๊ตฐ๊ฐ๊ฐ ์๊ฐ ์ด๊ณผ์ ์ทจ์๋ฅผ ๊ตฌ๋ณํ ์ ์๊ธฐ๋ฅผ ์ํ๋ ์ด์ ๋ฅผ ์ ์ ์๋ ๋ฌด์ํ ๋ง์ ๋ค๋ฅธ ์ด์ ๊ฐ ์์ต๋๋ค. ์ด์ ๊ฐ์ ์ผ๋ฐ์ ์ธ ์๋๋ฆฌ์ค์ ๋ํ ๋ ๋์ ์ง์์ด ์กด์ฌํ์ง ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ์ด์ ๋ ์ ๊ฐ ์ดํดํ๊ธฐ ํ๋ ๋ถ๋ถ์ด๋ฉฐ MS ํ์์ ์ถ๊ฐ๋ก ์๊ฐํด๋ณผ ์ ์๊ธฐ๋ฅผ ์ง์ฌ์ผ๋ก ๋ฐ๋๋๋ค.
@karelz ๋๊ตฐ๊ฐ์ API ์ ์์ธ 3.0์ ์ผ์ ์ ๋ง์ถฐ ์ด๊ฒ์ ์ป์ผ๋ ค๋ฉด ๋ฌด์์ด ํ์ํ ๊น์?
์ด๊ฒ์ API ์ ์์ ๊ดํ ๊ฒ์ด ์๋๋๋ค. ์ด๊ฒ์ ์ฌ๋ฐ๋ฅธ ๊ตฌํ์ ์ฐพ๋ ๊ฒ์
๋๋ค. ์ด๊ฒ์ 3.0 ๋ฐฑ๋ก๊ทธ์ ์์ผ๋ฉฐ ๋ชฉ๋ก์์ ์๋นํ ๋์ต๋๋ค(HTTP/2 ๋ฐ ์ํฐํ๋ผ์ด์ฆ ์๋๋ฆฌ์ค ๋ค์ ์์). ์ฐ๋ฆฌ ํ์ด 3.0์์ ํด๊ฒฐํ ์ ์๋ ์์ฃผ ์ข์ ๊ธฐํ์
๋๋ค.
๋ฌผ๋ก ์ปค๋ฎค๋ํฐ์์ ๋๊ตฐ๊ฐ๊ฐ ๋๊ธฐ๋ฅผ ๋ถ์ฌํ๋ฉด ์ฐ๋ฆฌ๋ ๊ธฐ์ฌ๋ฅผ ํ ๊ฒ์
๋๋ค.
@karelz ์ด ๊ฒฝ์ฐ ์ปค๋ฎค๋ํฐ๊ฐ ์ด๋ป๊ฒ ๋์์ ์ค ์ ์์ต๋๊น? API ์ ์์ด ํ์ํ๋ค๊ณ ์ธ๊ธํ ์ด์ ๋ "์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ ๋ ์ํํ ๋ช ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค."๋ก ์์ํ๋ ๋ฉ์์ง์์ ํ์ด ๋ชฉ๋ก์์ ์ ํธํ๋ ๋์์ ๊ฒฐ์ ํ๋์ง ํ์ ํ ์ ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋น์ ์ด ๋ฐฉํฅ์ ๊ฒฐ์ ํ๋ค๋ฉด ์ฐ๋ฆฌ๋ ๊ฑฐ๊ธฐ์์ ๊ฐ ์ ์์ต๋๋ค. ๊ฐ์ฌ ํด์!
๊ธฐ์ ์ ์ผ๋ก ๋งํ๋ฉด API ์ ์ ์ง๋ฌธ์ด ์๋๋๋ค. ๊ฒฐ์ ์๋ API ์น์ธ์ด ํ์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐจ์ด์ ์ ๋
ธ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์กฐ์ ํด์ผ ํ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ์ฝ๊ฐ์ ํ ๋ก ์ด ์์ ๊ฒ์
๋๋ค.
๊ตฌํ์์ ์ต์
์ด ๋๋ฌด ๋ง์ด ๋ค๋ฅผ ๊ฒ์ผ๋ก ๊ธฐ๋ํ์ง ์์ต๋๋ค. ์ปค๋ฎค๋ํฐ์์ ๋์์ ์ํ ๊ฒฝ์ฐ ์ต์
์ ๊ตฌํํ๋ฉด 98%๋ฅผ ์ป์ ์ ์์ต๋๋ค(์์ธ๊ฐ ํ ๊ณณ์์ ๋ฐ์ํ๊ณ ์์ ๋์ด๋ [1]-[3] ์ต์
์ ๋ง๊ฒ ๋์ค์ ์ฝ๊ฒ ๋ณ๊ฒฝ๋จ).
์๋ ! ์ฐ๋ฆฌ๋ ์ต๊ทผ์๋ ์ด ๋ฌธ์ ๋ฅผ ๊ฒช์์ต๋๋ค. ์ฌ์ ํ 3.0์ ๋ํ ๊ด์ฌ์ด ์๋์ง ๊ถ๊ธํ์ญ๋๊น?
์, ์ฌ์ ํ 3.0 ๋ชฉ๋ก์ ์์ต๋๋ค. 3.0์์ ํด๊ฒฐ๋ ๊ฐ๋ฅ์ฑ์ ์ฌ์ ํ โโ90%์ ๋๋ค.
๋๋ ์ค๋ ์ด๊ฒ์ ๋ง๋ฌ๋ค. ๋๋ HttpClient์ ์๊ฐ ์ด๊ณผ๋ฅผ ์ค์ ํ๊ณ ๊ทธ๊ฒ์ ๋์๊ฒ ์ด๊ฒ์ ์ค๋ค.
{System.Threading.Tasks.TaskCanceledException: A task was canceled.}
CancellationRequested = true
๋๋ ์ด๊ฒ์ด ๋ฌธ์ ๊ฐ๋๋ ์๊ฐ ์ด๊ณผ์ ๋ํด ์ธ๊ธํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ด ํผ๋ ์ค๋ฝ๋ค๋ ๊ฒ์ ๋์ํฉ๋๋ค.
์, ์๊ฒ ์ต๋๋ค. ์ฝ๊ฐ ํผ๋์ค๋ฝ์ต๋๋ค. ์ด ์ค๋ ๋์ ๋ชจ๋ ์ฌ๋๋ค์ HTTP ์๊ฐ ์ด๊ณผ๊ฐ TaskCanceledException
๋ฅผ ๋ฐ์์ํจ๋ค๊ณ ๋งํ๋ ๊ฒ ๊ฐ์ง๋ง ๊ทธ๊ฒ ์ ๊ฐ ์ป๋ ๊ฒ์ด ์๋๋๋ค... .NET Core 2.1์์ OperationCanceledException
๋ฅผ ๋ฐ๊ณ ์์ต๋๋ค...
์๊ฐ ์ด๊ณผ์ ๋ํด OperationCanceledException์ ๋ฐ์์ํค๊ณ ์ถ๋ค๋ฉด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง ์ ๋๋ก ๋ฌธ์ํ๋์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋์ฒด ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ถ์ ํ๋ ๋ฐ ๋ช ์๊ฐ์ ๋ณด๋์ต๋๋ค.
https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.sendasync
HttpRequestException
์๊ฐ ์ด๊ณผ๋ก ์ธํด ๋ฐ์ํ๋ค๊ณ ๋ช
ํํ๊ฒ ๋ช
์๋์ด ์์ต๋๋ค...
TaskCanceledException์ OperationCanceledException์์ ํ์๋ฉ๋๋ค.
@stephentoub ์, ํ์ง๋ง TaskCanceledException
๋ฅผ ๋ฐ์ง ๋ชปํ๊ณ OperationCanceledException
์ ๋ฐ์ต๋๋ค.
์์์ ๊ฐ์ด TaskCanceledException
๋ฅผ ์ก๋ catch ๋ธ๋ก์ ์์ธ๋ฅผ ํฌ์ฐฉํ์ง ์์ต๋๋ค. ํนํ OperationCanceledException
์ ๋ํ catch ๋ธ๋ก์ด ํ์ํฉ๋๋ค.
์ ๋ ์ด์ ์์ธ ์ ํ์ ํํฐ๋งํ์ฌ HTTP ์๊ฐ ์ด๊ณผ์ ๋ํด ๊ตฌ์ฒด์ ์ผ๋ก ํ
์คํธํ๊ณ ์์ผ๋ฉฐ ์๊ฐ ์ด๊ณผ์์ ์๋ ๋ฐฉ๋ฒ์ TaskCanceledException
์ด ์๋ ๊ฒฝ์ฐ์
๋๋ค.
```c#
๋
ธ๋ ฅํ๋ค {
(var ์๋ต = await s_httpClient.SendAsync(request, _updateCancellationSource.Token).ConfigureAwait(false)) ์ฌ์ฉ
return (int)response.StatusCode < 400;
}
catch (OperationCanceledException ex) when (ex.GetType() != typeof(TaskCanceledException)) {
// HTTP ํ์์์
๊ฑฐ์ง์ ๋ฐํํฉ๋๋ค.
}
catch(HttpRequestException) {
๊ฑฐ์ง์ ๋ฐํํฉ๋๋ค.
}
or alternatively this works as well, which might be better:
```c#
try {
using (var response = await s_httpClient.SendAsync(request, _updateCancellationSource.Token).ConfigureAwait(false))
return (int)response.StatusCode < 400;
}
catch (OperationCanceledException ex) when (ex.GetType() == typeof(OperationCanceledException)) {
// HTTP timeout
return false;
}
catch (HttpRequestException) {
return false;
}
์, ์๊ฒ ์ต๋๋ค. ์ฝ๊ฐ ํผ๋์ค๋ฝ์ต๋๋ค. ์ด ์ค๋ ๋์ ๋ชจ๋ ์ฌ๋๋ค์ HTTP ์๊ฐ ์ด๊ณผ๊ฐ
TaskCanceledException
๋ฅผ ๋ฐ์์ํจ๋ค๊ณ ๋งํ๋ ๊ฒ ๊ฐ์ง๋ง ๊ทธ๊ฒ ์ ๊ฐ ์ป๋ ๊ฒ์ด ์๋๋๋ค... .NET Core 2.1์์OperationCanceledException
๋ฅผ ๋ฐ๊ณ ์์ต๋๋ค...์๊ฐ ์ด๊ณผ์ ๋ํด OperationCanceledException์ ๋ฐ์์ํค๊ณ ์ถ๋ค๋ฉด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง ์ ๋๋ก ๋ฌธ์ํ๋์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋์ฒด ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ถ์ ํ๋ ๋ฐ ๋ช ์๊ฐ์ ๋ณด๋์ต๋๋ค.
https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.sendasync
HttpRequestException
์๊ฐ ์ด๊ณผ๋ก ์ธํด ๋ฐ์ํ๋ค๊ณ ๋ช ํํ๊ฒ ๋ช ์๋์ด ์์ต๋๋ค...
์๊ฐ ์ด๊ณผ๋ฅผ ๋ช ์์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ(๋ด๊ฐ ์ํ๋ ๋งํผ ๊นจ๋ํ์ง๋ ์์ง๋ง ๋ฐฉ๋ฒ)์ ๋ณด์ฌ์ฃผ๋ ์ฝ๋ ์์ ๋ฅผ ํฌํจํ์ฌ OperationCanceledExecption์ด ์ฐธ์กฐ๋๋ ์ค์ ๋ก ์ฌ๋ฌ ์๋ต์ด ์๊ธฐ ๋๋ฌธ์ ์ ์ฒด ์ค๋ ๋๋ฅผ ์ฝ์์ต๋๊น?
@Hobray ์, ๋ด๊ฐ ๊ฐ์ง๊ณ ์์ง ์๋ค๊ณ ์๊ฐํ๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ์ฌ์ ํ ์ด ์ค๋ ๋์ ์ผ๋ง๋ ๋ง์ ์ฌ๋๋ค์ด ์๊ฐ ์ด๊ณผ ์ TaskCanceledException
๋ฅผ ๋ฐ๊ณ ์๋์ง ์ค๋ช
ํ์ง ๋ชปํ์ง๋ง ์ ๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
๊ทํ์ ์ฝ๋ ์์ ๋ ๋ณด์์ง๋ง ๋ถํํ๋ ๊ทํ๊ฐ ๊ณ ๋ คํ์ง ์์ ๊ฒฝ์ ์กฐ๊ฑด์ด ์์ต๋๋ค. ๋ด๊ฐ ์ฌ์ฉํ๊ณ ์๋ ์ฝ๋๋ ์ด ๋ฌธ์ ๋ฅผ ํผํ๊ณ ์ทจ์ ํ ํฐ์ ๋ํ ์ก์ธ์ค๊ฐ ํ์ํ์ง ์๋ค๊ณ ๊ฒ์๋์ด ์์ต๋๋ค.
@mikernet ์๋ง๋ ๊ทธ ๋ฌธ๊ตฌ๊ฐ ๋๋ฅผ ๋ฒ๋ ธ์ ๊ฒ์ ๋๋ค. ๋ด๊ฐ ๊ฐ๋ฅํ ๊ฒฝ์ ์กฐ๊ฑด์ ๊ณ ๋ คํ์ง ์์ ๊ฒ์ด ๋ง์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ๋ฉ์ง ํด๊ฒฐ์ฑ ์ด ์๋๋ผ๋ ๊ฒ์ ์๊ณ ์์ง๋ง ๋ด๊ฐ ๊ฐ๊ณผ ํ ๊ฒ์ ์ค๋ช ํ๊ณ ์ถ๋ค๋ฉด ๋ฃ๊ณ ์ถ์ต๋๋ค.
๋ด๊ฐ ์์์ฐจ๋ฆฐ ํ ๊ฐ์ง๋ ์ปจํธ๋กค๋ฌ ๋ ๋ฏธ๋ค์จ์ด ํธ์ถ์์ ์๊ฐ ์ด๊ณผ ๋๋ ์ทจ์๊ฐ ๋ฐ์ํ๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ์ ํํ ์์ธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค๋ ๊ฒ์
๋๋ค. ๋ฏธ๋ค์จ์ด ํธ์ถ ๋ด๋ถ์๋ TaskCanceledException
์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๋ถํํ๋ ๋๋ ๊ทธ ์ด์ ๋ฅผ ์ดํดํ๊ธฐ ์ํด .NET Core ์ฝ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํํค์น ์๊ฐ์ด ์์ง๋ง ๋ด๊ฐ ์์์ฐจ๋ฆฐ ๊ฒ์
๋๋ค.
@Hobray ํํ ๋ฌผ๋ก ์ ๋๋ค. ์ฃ์กํฉ๋๋ค. ๊ฒฝ์ ์ํฉ์ ๋ํด ๋น๋ฐ์ค๋ฝ๊ฒ ๋งํ ์๋๋ ์์์ต๋๋ค. ์ด๋ ์ค์ ๋ง์ง๋ง ๋ฉ์์ง๋ฅผ ์ ๋ ฅํ๋ ๋์ ์ ํ๋ฅผ ๋ฐ๊ณ ์์๊ธฐ ๋๋ฌธ์ ์ค๋ช ํ๊ธฐ ์ด๋ ค์ ์ต๋๋ค.
HttpClient
์๊ฐ ์ด๊ณผ์ ์ทจ์ ํ ํฐ ์ทจ์ ์ํ๋ฅผ ํ์ธํ๋ ์ง์ ์ฌ์ด์ ์์
์ทจ์๊ฐ ์์๋ ๊ฒฝ์ฐ ์๋ฃจ์
์ ๊ฒฝ์ ์กฐ๊ฑด์ด ๋ฐ์ํฉ๋๋ค. ๋ด ์ํฉ์์๋ ์
์คํธ๋ฆผ ์ฝ๋๊ฐ ์ฌ์ฉ์ ์ทจ์๋ฅผ ๊ฐ์งํ ์ ์๋๋ก ๊ณ์ ๋ฒ๋ธ๋งํ๋ ค๋ฉด ์์
์ทจ์ ์์ธ๊ฐ ํ์ํ๋ฏ๋ก ์ค์ ๋ก ์๊ฐ ์ด๊ณผ๋ ๊ฒฝ์ฐ์๋ง ์์ธ๋ฅผ catchํ ์ ์์ด์ผ ํฉ๋๋ค. ๊ทธ๋์ when
๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์บ์น๋ฅผ ํํฐ๋งํฉ๋๋ค. ํ ํฐ ๊ฒ์ฌ ์๋ฃจ์
์ ์ฌ์ฉํ๋ฉด ์ฒ๋ฆฌ๋์ง ์์ OperationCanceledException
๊ฐ ํํฐ๋ฅผ ํต๊ณผํ๊ณ ํ๋ก๊ทธ๋จ์ด ๋ฒ๋ธ๋ง๋๊ณ ์ถฉ๋์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์๋ํ๋ฉด ๋๊ตฐ๊ฐ ์
์คํธ๋ฆผ์์ ์์
์ ์ทจ์ํ๋ฉด TaskCanceledException
๊ฐ ๋์ ธ์ง๋ ๊ฒ์ด ์๋๋ผ ๋์ง ๊ฒ์ผ๋ก ์์ํ๊ธฐ ๋๋ฌธ์
๋๋ค. OperationCanceledException
.
HttpClient
๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์ฝ๋๊ฐ ์๊ฐ ์ด๊ณผ์ ์์
์ทจ์๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฒฝ์ฐ ๊ฒฝ์ ์กฐ๊ฑด์ด ๋ฐ์ํ ๋ ์๊ฐ ์ด๊ณผ์ ์ฌ์ฉ์ ์ทจ์ ๊ฐ์ ๊ตฌ๋ณ์ ์ํฉ์ ๋ฐ๋ผ ์ค์ ํ์ง ์์ ์ ์์ต๋๋ค... ๊ทธ๋ฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ค ์ฝ๋๋ฅผ ์์ฑ ์ค์ด๊ณ ์์
์ทจ์ ๋ฒ๋ธ์ด ๋ ๋์ ์์ค์์ ์ฒ๋ฆฌ๋๋๋ก ํด์ผ ํ๋ ๊ฒฝ์ฐ ํ์คํ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
๋น์ ์ด ๋งํ๋ ๊ฒ์ด ์ฌ์ค์ด๊ณ ํธ์ถ ์ปจํ ์คํธ๊ฐ ๋ฌด์์ธ์ง์ ๋ฐ๋ผ ์๊ฐ ์ด๊ณผ๊ฐ ๋ค๋ฅธ ์์ธ ์ ํ์ ๋์ง๋ค๋ฉด ๊ทธ๊ฒ์ ๋ถ๋ช ํ ํด๊ฒฐํด์ผ ํ ๋ฌธ์ ์ฒ๋ผ ๋ณด์ ๋๋ค. ์๋๋ ๋์์ด๊ฑฐ๋ ๊ทธ๋์ผ ํ๋ ๋ฐฉ๋ฒ์ ์์ต๋๋ค.
๊ฐ๋ฅํ ๊ฒฝ์ ์กฐ๊ฑด์ ํฅ๋ฏธ๊ฐ ์์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ ๊ณ ๋ คํ์ง ์์๋ค. ์ด ์ข๊ฒ๋ ์ ์ฌ์ฉ ์ฌ๋ก์์๋ ํฐ ๋ฌธ์ ๊ฐ ๋์ง ์์ ๊ฒ์ ๋๋ค.
์์ธ ๋ณํ์ ๊ดํด์๋ ๋๋ฒ๊น ํ๋ ๋์ ๋ช ๋ฒ ๋ณธ ๊ฒ๊ณผ ์ผ์นํ๋์ง ํ์ธํ๊ธฐ ์ํด ์์ ํ๊ณ ์๋ ๋ฏธ๋ค์จ์ด๋ฅผ ๋ฒ์ด๋ฆฌ๋ก ๋ง๋ค ์๊ฐ์ด ํ์ํฉ๋๋ค. ์ด๋ฆฌ์์ Chrome ๊ฒ์์ฃผ์์ฐฝ ์ฌ์ ๋ก๋ ํธ์ถ์ ํ์ด๋ฐ์ด ์ ์ ํ์ ๋ ๋ฏธ๋ค์จ์ด์์ ๋ณธ ์ ์ด ์์ต๋๋ค. ์ด๋ค ์์ผ๋ก๋ ๊ทธ๊ฒ์ ํ์คํ ์ฆ๋ช ํ ์ ์๋ ๊ฐ๋จํ ์๋ฅผ ๋ง๋ค ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ฌ๋ฐ๋ฅธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ์์ง ํ์คํ์ง ์์ต๋๋ค.
๋ด ์๋ฃจ์ ์ http ์๊ฐ ์ด๊ณผ๋ก ์ธํด OperationCanceledException์ด ๋ฐ์ํ๋ ์ํฉ์์ ๊ฐ์ฅ ์ ํํฉ๋๋ค. TaskCanceledException์ด ๋ฐ์ํ๊ณ ์๋ฌด๋ ํด๋น ๋์์ ์ฌํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์์ ์ํฉ์ ์ฌํํ ์ ์์ผ๋ฏ๋ก ํ๊ฒฝ์ ํ ์คํธํ๊ณ ๋์ ์ผ์นํ๋ ๊ฒฝ์ฐ ์ฌ๋ฐ๋ฅธ ์๋ฃจ์ ์ด๋ผ๊ณ ๋งํฉ๋๋ค.
์ผ๋ถ ์คํ ์ปจํ ์คํธ์์ TaskCanceledException์ด ๋ฐ์ํ๋ฉด ๋ด ์๋ฃจ์ ์ด ํด๋น ์ปจํ ์คํธ์ ๋ํ ๋ฒ์ฉ ์๋ฃจ์ ์ผ๋ก ์คํจํ๊ณ ์ ์๋ ๋ค๋ฅธ ์๋ฃจ์ ์ด "์ต์์" ์๋ฃจ์ ์ด์ง๋ง ์ํฉ์ ์ค์ํ๊ฑฐ๋ ์ค์ํ์ง ์์ ์ ์๋ ๊ฒฝ์ ์กฐ๊ฑด์ด ํฌํจ๋ ๊ฒฝ์ฐ ๋น์ ์ ํ๊ฐํฉ๋๋ค.
๋ถ๋ช ํ ํฐ ๋ฒ๊ทธ๊ฐ ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ TaskCanceledExceptions๊ฐ ๋ฐ์ํ๋ค๊ณ ์ฃผ์ฅํ๋ ์ฌ๋์ ์์ธํ ๋ด์ฉ์ ๋ฃ๊ณ ์ถ์ต๋๋ค. ๋๋ ์ด๊ฒ์ด ์ค์ ๋ก ์ผ์ด๋๊ณ ์๋์ง์ ๋ํด ๋ค์ ํ์์ ์ด๋ค.
@mikernet TaskCanceledException
๋๋ OperationCanceledException
๊ฐ ๋์ ธ์ก๋์ง ์ฌ๋ถ๋ ํฌ๊ฒ ๊ด๋ จ์ด ์์ต๋๋ค. ์ด๊ฒ์ ์์กดํด์๋ ์ ๋๋ ๊ตฌํ ์ธ๋ถ ์ฌํญ์
๋๋ค. ๋น์ ์ด ํ ์ ์๋ ์ผ์ OperationException
( TaskCanceledException
๋ ์ก์ ๊ฒ์
๋๋ค)๋ฅผ ์ก์๋ด๊ณ Hobray์ ์ฝ๋ฉํธ(https://github.com/)์ ์ค๋ช
๋ ๋๋ก ์ ๋ฌํ ์ทจ์ ํ ํฐ์ด ์ทจ์๋์๋์ง ํ์ธํ๋ ๊ฒ์
๋๋ค. dotnet/corefx/issues/20296#issuecomment-449510983).
@thomaslevesque ๋๋ ์ด๋ฏธ ๊ทธ ์ ๊ทผ ๋ฐฉ์์ด ๋ฌธ์ ์ธ ์ด์ ๋ฅผ ์ธ๊ธํ์ต๋๋ค. ๊ทธ๊ฒ์ ๋ค๋ฃจ์ง ์์ผ๋ฉด ๊ทํ์ ์๊ฒฌ์๋ณ๋ก ์ ์ฉํ์ง ์์ต๋๋ค. ๋ด๊ฐ ์ค๋ช ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ์๊ณ ๋ณํ์ ์ฐธ์ฌํ๊ธฐ ์ ์ ์ง์ ์ ๋ค์ ํด์ํ๋ ๊ฒ์ ๋๋ค.
"๊ตฌํ ์ธ๋ถ ์ฌํญ"์ ๊ดํด์๋ - ๊ทธ๋ ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ถํํ๋ ๋๋ ๊ทธ๊ฒ์ ์์กดํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์์
์ด ์ค์ ๋ก ์ทจ์๋์๊ฑฐ๋ ์๊ฐ ์ด๊ณผ๋์๋์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ข์ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ค๋ช
๋ ๊ฒฝ์ ์กฐ๊ฑด์ ํผํ๊ธฐ ์ํด ๋ ์๋๋ฆฌ์ค ์ค ์ด๋ค ๊ฒ์ด ๋ฐ์ํ๋์ง๋ฅผ ์์ธ๋ก๋ถํฐ 100% ๊ฒฐ์ ํ๋ ๋ฐฉ๋ฒ์ด ์์ด์ผ ํฉ๋๋ค. OperationCanceledException
๋ ์ด ๋๋ฌธ์ ์ข์ง ์์ ์ ํ์
๋๋ค...ํ๋ ์์ํฌ์๋ ์ด๋ฏธ TimeoutException
๊ฐ ์์ด ๋ ๋์ ํ๋ณด์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
๋น๋๊ธฐ ์์ ์ ๋ํ ์์ธ๋ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ธ์ ์์ธ์ ๊ธฐ๋ฐ์ผ๋ก ๋ถ๊ธฐ ๊ฒฐ์ ์ ๋ด๋ฆฌ๋ ๊ฒ์ด๋ผ๋ฉด ์์ธ์ ์์ธ์ ํ์ธํ๊ธฐ ์ํด ๋น๋๊ธฐ์ ์ผ๋ก ์์ ํ ์๋ ์๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฐ์ดํฐ ํ์ธ์ ์์กดํด์๋ ์ ๋ฉ๋๋ค. ๊ทธ๊ฒ์ ๊ฒฝ์ ์กฐ๊ฑด ๋ฌธ์ ๋ฅผ ๊ตฌ๊ฑธํ๋ ๊ฒ์ ๋๋ค.
๋ํ ์์ธ ์ ํ์ด ๊ตฌํ ์ธ๋ถ ์ฌํญ์ด๋ผ๋ ์ธก๋ฉด์์...์ ๋ ์์ธ์ ๋ํด ๊ทธ๊ฒ์ด ์ฌ์ค์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์ ์ด๋ ์ ํ๋ฆฝ๋ .NET ๋ฌธ์ ๊ดํ์ ๊ด์ ์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค. .NET Framework์์ ๋ฌธ์์ "Y๊ฐ ๋ฐ์ํ๋ฉด ์์ธ X๊ฐ ๋ฐ์ํฉ๋๋ค"๋ผ๊ณ ๋ช ์๋์ด ์๊ณ ํ๋ ์์ํฌ๊ฐ ์ค์ ๋ก ํด๋น ์์ธ์ ๊ณต๊ฐ์ ์ผ๋ก ์ก์ธ์คํ ์ ์๋ ํ์ ํด๋์ค๋ฅผ ๋ฐ์์ํค๋ .NET Framework์ ๋ค๋ฅธ ์ ๋ฅผ ๋ค์ด ๋ณด์ญ์์ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ TaskCanceledException
๋ ์๊ฐ ์ด๊ณผ๊ฐ ์๋๋ผ ์ฌ์ฉ์๊ฐ ์์ํ ์์
์ทจ์๋ฅผ ์ํด ์์ฝํด์ผ ํฉ๋๋ค. ์์ ๋งํ๋ฏ์ด ์ด๋ฏธ ์์ธ๊ฐ ์์ต๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ด๋ถ ์์
์ทจ์๋ฅผ ์บก์ฒํ๊ณ ๋ ์ ์ ํ ์์ธ๋ฅผ ๋ฐ์์์ผ์ผ ํฉ๋๋ค. ์์
์ทจ์ ํ ํฐ์ผ๋ก ์์๋ ์์
์ทจ์์ ๋ํ ์์ธ ์ฒ๋ฆฌ๊ธฐ๋ ๋น๋๊ธฐ ์์
์ค์ ๋ฐ์ํ ์ ์๋ ๋ค๋ฅธ ๊ด๋ จ ์๋ ๋ฌธ์ ๋ฅผ ์ฒ๋ฆฌํ ์ฑ
์์ด ์์ต๋๋ค.
@mikernet ์ฃ์กํฉ๋๋ค. ํ ๋ก ์์ ๊ทธ ๋ถ๋ถ์ ๋์ณค์ต๋๋ค. ์, ์๊ฐํ์ง ๋ชปํ ๊ฒฝ์ ์กฐ๊ฑด์ด ์์ต๋๋ค. ํ์ง๋ง ์๊ฐ๋ณด๋ค ํฐ ๋ฌธ์ ๋ ์๋์ง๋... ํ์์์์ด ๋ฐ์ํ ํ ํ ํฐ์ ์ํ๋ฅผ ํ์ธํ๊ธฐ ์ ์ ์ทจ์ ํ ํฐ์ด ์ ํธ๋ฅผ ๋ฐ์ผ๋ฉด ๊ฒฝ์ ์กฐ๊ฑด์ด ๋ฐ์ํฉ๋๋ค. ๊ทธ๋ ์ฃ ? ์ด ๊ฒฝ์ฐ ์์
์ด ์ด์จ๋ ์ทจ์๋๋ ๊ฒฝ์ฐ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ๋์ง ์ฌ๋ถ๋ ์ค์ ๋ก ์ค์ํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ OperationCanceledException
๋ฒ๋ธ์ด ๋ฐ์ํ๋๋ก ํ์ฌ ํธ์ถ์๊ฐ ์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์ทจ์๋์๋ค๊ณ ๋ฏฟ๊ฒ ํฉ๋๋ค. ์ด๋ ์ค์ ๋ก ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๊ฑฐ์ง๋ง์ด์ง๋ง ํธ์ถ์๋ ๋ค์์ ์ํ๊ธฐ ๋๋ฌธ์ ์ค์ํ์ง ์์ต๋๋ค. ์ด์จ๋ ์์
์ ์ค๋จํฉ๋๋ค.
์ค๋ช ๋ ๊ฒฝ์ ์กฐ๊ฑด์ ํผํ๊ธฐ ์ํด ๋ ์๋๋ฆฌ์ค ์ค ์ด๋ค ๊ฒ์ด ๋ฐ์ํ๋์ง๋ฅผ ์์ธ๋ก๋ถํฐ 100% ๊ฒฐ์ ํ๋ ๋ฐฉ๋ฒ์ด ์์ด์ผ ํฉ๋๋ค.
OperationCanceledException
๋ ์ด ๋๋ฌธ์ ์ข์ง ์์ ์ ํ์ผ ๋ฟ์ ๋๋ค. ํ๋ ์์ํฌ์๋ ์ด๋ฏธTimeoutException
๊ฐ ์์ด ๋ ๋์ ํ๋ณด์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
๋๋ ์ ์ ์ผ๋ก ๋์ํฉ๋๋ค. ํ์ฌ์ ํ๋์ ๋ถ๋ช ํ ์๋ชป๋์์ต๋๋ค. ๋ด ์๊ฒฌ์ผ๋ก๋ ๊ทธ๊ฒ์ ๊ณ ์น ์ ์๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ @karelz ์ ์๊ฒฌ ์์ ์ต์ 1์ ๋๋ค. ์, ๊ทธ๊ฒ์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด์ง๋ง ๋๋ถ๋ถ์ ์ฝ๋ ๊ธฐ๋ฐ์ด ์ด์จ๋ ์ด ์๋๋ฆฌ์ค๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ง ์๊ณ ์๋ค๊ณ ์๊ฐํ๋ฏ๋ก ์ํฉ์ ์ ํ์ํค์ง๋ ์์ ๊ฒ์ ๋๋ค.
@thomaslevesque ๊ธ์์, ํ์ง๋ง ์ ๋ ๊ทธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค. ์ผ๋ถ ์์ฉ ํ๋ก๊ทธ๋จ์์๋ ์ค์ํ๊ฑฐ๋ ์ค์ํ์ง ์์ ์ ์์ต๋๋ค. ์ ๊ฒฝ์ฐ์๋ ๊ทธ๋ ์ต๋๋ค. ๋ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐฉ๋ฒ์ ์ฌ์ฉ์๋ ์์
์ ์ทจ์ํ ๋ OperationCanceledException
๋ฅผ ๊ธฐ๋ํ์ง ์์ต๋๋ค. TaskCanceledException
๋ฅผ ๊ธฐ๋ํ๊ณ ์์ผ๋ฉฐ ์ด๋ฅผ ์ก์์ "์์ "ํ ์ ์์ด์ผ ํฉ๋๋ค. ์ทจ์ ํ ํฐ์ ํ์ธํ๊ณ ์ทจ์๋ ๊ฒ์ ํ์ธํ๊ณ ์์ธ๋ฅผ ์ ๋ฌํ๋ฉด ์ฒ๋ฆฌ๊ธฐ์ ์ํด ํฌ์ฐฉ๋์ง ์๊ณ ํ๋ก๊ทธ๋จ์ด ์ถฉ๋ํ๋ ์์ธ๋ฅผ ๋ฐฉ๊ธ ์ ๋ฌํ ๊ฒ์
๋๋ค. ๋ด ๋ฐฉ๋ฒ์ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํด์๋ ์๋ฉ๋๋ค.
๋ฌผ๋ก , ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค...์๋ก ๋ํ๋ TaskCanceledException
๋ฅผ ๋์ง ์ ์์ง๋ง ๊ทธ๋ฌ๋ฉด ์ต์์ ์คํ ์ถ์ ์ด ์์ค๋๊ณ HTTP ์๊ฐ ์ด๊ณผ๋ ๋ด ์๋น์ค์ ์์
์ทจ์์ ํจ์ฌ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌ๋ฉ๋๋ค. - HTTP ์๊ฐ ์ด๊ณผ๋ ์ด๋ ์ค๋ ์๊ฐ ๋์ ์บ์์ ์ ์ฅ๋์ง๋ง ์์
์ทจ์๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ๊ฒฝ์ ์กฐ๊ฑด์ผ๋ก ์ธํด ์ค์ ์๊ฐ ์ด๊ณผ๋ฅผ ์บ์ฑํ๋ ๊ฒ์ ๋์น๊ณ ์ถ์ง ์์ต๋๋ค.
OperationCanceledException
๋ฅผ ์ก๊ณ ์ทจ์ ํ ํฐ์ ํ์ธํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ์ทจ์๋ ๊ฒฝ์ฐ ์ ์ฒด ํ๋ก๊ทธ๋จ ์ถฉ๋์ ํผํ๊ธฐ ์ํด ๋ค์ ๋์ง๊ธฐ ์ ์ ์์ธ ์ ํ์ ํ์ธํ์ฌ TaskCanceledException
์ธ์ง ํ์ธํ์ญ์์ค. ์ด๋ฌํ ์กฐ๊ฑด ์ค ํ๋๋ผ๋ ๊ฑฐ์ง์ด๋ฉด ์๊ฐ ์ด๊ณผ์ฌ์ผ ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ๋จ์ ์๋ ๋ฌธ์ ๋ ๊ฒฝํฉ ์ํ๊ฐ ๋ฏธ๋ฌํ์ง๋ง ๋นก๋นกํ ์๊ฐ ์ด๊ณผ๊ฐ ์ค์ ๋ ๊ณผ๋ถํ ์๋น์ค์์ ๋ถ๋น ์์ฒ ๊ฐ์ HTTP ์์ฒญ์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ ๋ฐ์ํฉ๋๋ค.
์ด๋ ์ชฝ์ด๋ ๊ทธ๊ฒ์ ํดํค์ด๋ฉฐ ๋น์ ์ด ์ง์ ํ๋๋ก ์ด๋ป๊ฒ ๋ ํด๊ฒฐ๋์ด์ผํฉ๋๋ค.
(๊ฒฝํฉ ์กฐ๊ฑด์ OperationCanceledException
๋์ TaskCanceledException
๊ฐ ๋ฐ์ํ๋ ํ๊ฒฝ์์๋ง ๋ฐ์ํ์ง๋ง, ์ ์ด๋ ์๋ฃจ์
์ ์๊ธฐ์น ์์ ์์ธ ์ ํ์ ๋ฒ๋ธ๋งํ๋ ๊ฒ์ผ๋ก๋ถํฐ ์์ ํ๊ณ ๋ฐ์ํ์ง ์์ต๋๋ค. ๊ตฌํ ์ธ๋ถ ์ ๋ณด๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ์๋ ์ฌ์ ํ ํฉ๋ฆฌ์ ์ผ๋ก ์ ์๋ํ๋ ค๋ฉด ๊ตฌํ ์ธ๋ถ ์ ๋ณด์ ์์กดํด์ผ ํฉ๋๋ค.
http ์๊ฐ ์ด๊ณผ์ ๊ฒฝ์ฐ HttpClient
์์ ๋ฐ์ํ๋ ์๊ฐ ์ด๊ณผ ์์ธ๋ ์ผ๋ฐ System.TimeoutException
๋์ System.Net.HttpRequestException
(๋๋ ํ์ ํญ๋ชฉ?) ์ ํ์ด ์๋์ด์ผ ํฉ๋๊น? ์๋ฅผ ๋ค์ด, ์ข์ ์ค๋๋ WebClient
๋ $# WebExceptionStatus.Timeout
๋ก ์ค์ ํ ์ ์๋ Status
์์ฑ๊ณผ ํจ๊ป WebException
#$๋ฅผ ๋ฐ์์ํต๋๋ค.
์ํ๊น๊ฒ๋ 3.0์์๋ ์ด ์์
์ ์๋ฃํ ์ ์์ต๋๋ค. ๋ฏธ๋๋ก ์ด๋ํฉ๋๋ค.
์ฌ์ ํ ๋ฐฑ๋ก๊ทธ ์๋จ์ ์์ง๋ง ํ์ค์ ์ผ๋ก 3.0์์๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค :(.
@karelz oh no :(๋ ๋ฒ์งธ ํ์ฌ์์ ์ฐ์์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ๊ฒช์๋ ๋ฐฉ๋ฒ์ ๋ค์ ๊ฒ์ํ๋ ค๊ณ ํ์ต๋๋ค. ๋ด๊ฐ ์ง์ ํด๊ฒฐํ๋ ค๋ฉด 3.0์ ๋ํ PR ์ ์ถ ๊ธฐ๊ฐ์ด ์ผ๋ง๋ ๋ ๊น์? ๊ฑด๋ฐฐ
์ปจํ ์คํธ์ ๋ฐ๋ผ TaskCancelledException๊ณผ OperationCancelledException์ ๋ฐ๋ ๊ฒ ์ฌ์ด์ ์ฐจ์ด์ ์ ๋ณด๊ณ ํ๋ ์ฌ๋๋ค๊ณผ ํจ๊ป ์์ ๋ง์ ์ฃผ์์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ํํ ์ถ์ ํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช๊ณ ์์ต๋๋ค. MSFT์ ๋๊ตฌ๋ ์ง ์ด๋ฅผ ๋ฐํ ์ ์์ต๋๊น?
@mikernet ์ ์ด ๋๊ธ ์ข์์:
์์์ ๊ฐ์ด TaskCanceledException์ ์ก๋ catch ๋ธ๋ก์ ์์ธ๋ฅผ catchํ์ง ์์ต๋๋ค. ํนํ OperationCanceledException์ ๋ํ catch ๋ธ๋ก์ด ํ์ํฉ๋๋ค.
cc @davidsh @stephentoub ์๋ง๋?
TaskCanceledException์ OperationCanceledException์์ ํ์๋๋ฉฐ ์ฝ๊ฐ์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๋ฌํฉ๋๋ค. OperationCanceledException์ ์ก์ผ๋ฉด ๋ฉ๋๋ค.
@karelz ๋ ์๋ ๊ฒ์ํ ์ต์ 1์ ์ฌ์ฉํ์ฌ ์๊ฐ ์ด๊ณผ ์์ธ๋ฅผ ๋ฐ์์ํค๋ฉด ์์ ํ ๋ถ์พํฉ๋๊น?
StackExchange.Redis์ ๊ฐ์ ๊ฒ๋ค์ Timeout ์์ธ์์ ํ์๋ ์์ธ๋ฅผ ๋์ง๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ HttpClient์ ๋ํ Timeout ์์ธ๋ฅผ ์ก๋ ๊ฒ์ด ์ข์ ๊ฒ์ ๋๋ค...
์์์ด ์ฃผ์ด์ง @stephentoub ๋ฅผ ์ดํดํฉ๋๋ค. @mikernet์ ์๋ ๋๊ธ์ด ์ ๋ง์์ ๋ค๋จ๊ฒ ํฉ๋๋ค... ๊ทธ๊ฐ ์ค๋ช ํ๋ ์ด ํ๋์ ์ผ์ข ์ ๋ฒ๊ทธ์ฌ์ผ ํ๋ ๊ฑด๊ฐ์?? ๊ทธ๋ฌ๋ ์ฌ์ค์ด๋ผ๋ฉด ์์ ๋๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ํฅ์ ๋ฏธ์น ๊ฒ์ ๋๋คโฆ
"TaskCanceledException์ catchํ๋ catch ๋ธ๋ก์ ์์ธ๋ฅผ catchํ์ง ์์ต๋๋ค. ํนํ OperationCanceledException์ ๋ํ catch ๋ธ๋ก์ด ํ์ํฉ๋๋ค."
์๋๋ฉด OperationEx๋ฅผ ๋์ง๋ ๊ณณ๋ ์๊ณ TaskEx๋ฅผ ๋์ง๋ ๊ณณ๋ ์๋ค๋ ๋ง์์ด์ ๊ฐ์? ์๋ง๋ ์ฌ๋๋ค์ด ASP ๋ฏธ๋ค์จ์ด์์ ์ค๋ ๊ฒ์ ๋ณด๊ณ HttpClient์์ ์จ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ ๊ฒ์ฒ๋ผ?
@mikernet ์์ ์๋์ ์ด ๋๊ธ์ด ์ ๋ง์์ ๋ถ๊ณ ์์ต๋๋ค... ๊ทธ๊ฐ ์ค๋ช ํ๋ ์ด ๋์์ ์ผ์ข ์ ๋ฒ๊ทธ์ฌ์ผ ํฉ๋๊น??
๊ทธ๊ฒ ์ "๋ง์์ด ํ๋ค๋ฆฌ๋" ๊ฒ์ ๋๊น? ์์ธ B๊ฐ ์์ธ A์์ ํ์๋๋ ๊ฒฝ์ฐ B์ ๋ํ catch ๋ธ๋ก์ ๊ตฌ์ฒด์ ์ผ๋ก A์ธ ์์ธ๋ฅผ catchํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ArgumentNullException์ ๋ํ catch ๋ธ๋ก์ด ์๋ ๊ฒฝ์ฐ " throw new ArgumentException(...)"์ catchํ์ง ์์ต๋๋ค.
์๋๋ฉด OperationEx๋ฅผ ๋์ง๋ ๊ณณ๋ ์๊ณ TaskEx๋ฅผ ๋์ง๋ ๊ณณ๋ ์๋ค๋ ๋ง์์ด์ ๊ฐ์?
์ค๋ฅธ์ชฝ. ์ผ๋ฐ์ ์ผ๋ก ์ฝ๋๋ OCE๋ง ๊ฐ์ ํด์ผ ํฉ๋๋ค. ์์ฑ ๋ฐฉ์์ ๋ฐ๋ผ ์ผ๋ถ ์ฝ๋๋ ํ์๋ TCE๋ฅผ ๋ฐ์์ํฌ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด TaskCompletionSource.TrySetCanceled๋ฅผ ํตํด ์๋ฃ๋ ์์ ์ TaskCanceledException์ ์์ฑํฉ๋๋ค.
Stephen, ๊ฐ์ฌํฉ๋๋ค. ์ค๋ ๋์ ์๋ฆฌ์์ ์ฌ๋ฌ ์ฌ๋์ด TaskCE๊ฐ ๋ชจ๋ ๊ณณ์์ ๋ฐ์ํ๊ณ ์๋ค๋ ์ธ์์ ๋ฐ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด mikernet์์ ์ธ๊ธํ ๋์์ด ์๋ฏธ๊ฐ ์์์ ๊ฒ์ ๋๋ค... ์ด์ ๋ช ํํ๊ฒ ํ์ผ๋, ๋ ผ๋ฆฌ์ ๊ด์ฐฐ :)
@stephentoub , ์ด ์ง์นจ์ด ์ด๋์๋ ๋ฌธ์ํ๋์ด ์์ต๋๊น? ํ @guardrex
์ผ๋ฐ์ ์ผ๋ก ์ฝ๋๋ OCE๋ง ๊ฐ์ ํด์ผ ํฉ๋๋ค...
์ ๋ ์์ฆ ASP.NET ๋ฌธ์ ์ธํธ๋ฅผ ์์ ํฉ๋๋ค. dotnet/docs ๊ณ ์์ด์ ๋ํ ๋ฌธ์ ์ด๊ธฐ ...
@karelz ๋ฐ @davidsh ์์ ๊ตฌ์ฒด์ ์ธ ์ ์์ด ์์๋ ๊ณณ์์ ์ด ๋ํ๋ฅผ ๋ค์ ์์ํ ์ ์์ต๋๊น? HttpClient API ๋ชจ๋ธ์ ์์ ๊ถ์ด ์๋ ๋๊ตฐ๊ฐ๊ฐ ๋์๊ฐ ๋ฐฉํฅ์ ๋ํ ๊ฒฐ์ ์ ๋ด๋ ค์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋๊ปด์ง๋๋ค. WebExceptionStatus์ ์ ์ฌํ ์๋ก์ด ์ด๊ฑฐํ ์์ฑ์ ํฌํจํ๋๋ก HttpRequestion์ ์์ ํ๊ธฐ ์ํด ๋ ํฐ ๋ฆฌํฉํฐ๋ง์ ๋ํ ์ฅ๊ธฐ์ ์ผ๋ก ๋ณด์ด๋ ์ฃผ์ ์ ํจ๊ป ํญ์ HttpRequestException(๋ช ์์ ์ทจ์ ์ ์ธ??)์ธ ์ต์์ ์์ธ์ ๋ํ ๋ช ๊ฐ์ง ๋ ผ์๊ฐ ์์์ต๋๋ค.
์ด ์ ์ฒด ๋ฌธ์ ๊ฐ ํ์ํ ์ค์ ์ฝ๋ ๋ณ๊ฒฝ๊ณผ ๊ด๋ จํ์ฌ ๋ณต์กํด์ง๋ ๊ฒ์ฒ๋ผ ๋๊ปด์ง๋๋ค. ์ผ๋ถ ๊ฒฐ์ ์ ๋ด๋ฆฌ๊ธฐ ์ํด ๋ฐ๋ณต๋์ด์ผ ํ๋ HttpClient API ๋ชจ๋ธ์ ์ง๋ถ/์์ ๊ถ์ ๊ฐ์ง ๋ค๋ฅธ ์ฌ๋๋ค์ด ์์ต๋๊น? ๊ฐ์ฌํฉ๋๋ค!
์ฌ๊ธฐ์ ๋์ผํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ cancellationToken.IsCancellationRequested
๊ฐ true
๋ฅผ ๋ฐํํฉ๋๋ค.
public class TimeoutHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
var response = await base.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode();
return response;
}
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
{
throw new TimeoutException("Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.");
}
}
๊ฐ์ ๋ก ํ์์์์ ํ๊ณ ์์ต๋๋ค. ๋ฐ์ํ ์์ธ๋ TaskCancelledException
IOException
์
๋๋ค.
System.Threading.Tasks.TaskCanceledException: The operation was canceled. ---> System.IO.IOException: Unable to read data from the transport connection: A operaรงรฃo de E/S foi anulada devido a uma saรญda de thread ou a uma requisiรงรฃo de aplicativo. ---> System.Net.Sockets.SocketException: A operaรงรฃo de E/S foi anulada devido a uma saรญda de thread ou a uma requisiรงรฃo de aplicativo
--- End of inner exception stack trace ---
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.GetResult(Int16 token)
at System.Net.Http.HttpConnection.FillAsync()
at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
...
(๋ฒ์ญ๋ ์์ธ ํ ์คํธ์ ๋ํด ์ฃ์กํฉ๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ์ด๊ฒ์ .NET Core์๋ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์ข์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค.)
๋ณด์๋ค์ํผ IsCancellationRequest
์ ํ์ธํ์ฌ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ ์ํ ๋๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ํ์ง๋ง ์๊ฐ ์ด๊ณผ ์์๋ true
๊ฐ ๋ฐํ๋ฉ๋๋ค.
ํ์ฌ ๊ตฌ์ฑ๋ ์๊ฐ ์ด๊ณผ๊ฐ ๊ฒฝ๊ณผํ๋์ง ํ์ธํ๊ธฐ ์ํด ํ์ด๋จธ๋ฅผ ๊ตฌํํ๋ ค๊ณ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ถ๋ช
ํ ๋๋ ์ฃฝ๊ณ ์ถ์ต๋๋ค . ์ด๊ฒ์ ๋์ฐํ ํด๊ฒฐ ๋ฐฉ๋ฒ์
๋๋ค.
์๋ ํ์ธ์ @FelipeTaveira ,
์ทจ์๊ฐ TimeoutHandler
์ ์
์คํธ๋ฆผ์์ HttpClient
์์ฒด์ ์ํด ์ฒ๋ฆฌ๋๊ธฐ ๋๋ฌธ์ ์ ๊ทผ ๋ฐฉ์์ด ์๋ํ์ง ์์ต๋๋ค. ํธ๋ค๋ฌ๋ Timeout
๊ฐ ๋ฐ์ํ ๋ HttpClient
์ ์ํด ์ทจ์๋๋ ์ทจ์ ํ ํฐ์ ๋ฐ์ต๋๋ค. ๋ฐ๋ผ์ ์ทจ์ ํ ํฐ์ด ์ทจ์๋์ง ์์๋์ง ํ์ธํ๋ ๊ฒ์ HttpClient
์ ์ํด ํธ์ถ๋ ์ฝ๋๊ฐ ์๋๋ผ HttpClient
๋ฅผ ํธ์ถํ๋ ์ฝ๋์์๋ง ์๋ํฉ๋๋ค.
์ฌ์ฉ์ ์ ์ ํธ๋ค๋ฌ์ ํจ๊ป ์๋ํ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ $#$8 Timeout.InfiniteTimeSpan
#$ ๋ก ์ค์ ํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์์ฒด ํธ๋ค๋ฌ์์ ์๊ฐ ์ด๊ณผ ๋์์ ์ ์ดํ์ฌ HttpClient
์ Timeout
๋ฅผ ๋นํ์ฑํํ๋ ๊ฒ์
๋๋ค. ์ด ๊ธฐ์ฌ ์ ํ์๋จ(์ ์ฒด ์ฝ๋๋ ์ฌ๊ธฐ )
@thomaslevesque ์ค, ๊ฐ์ฌํฉ๋๋ค! ๋๋ ๊ทํ์ ์ฝ๋๋ฅผ ์ฝ๊ณ ๊ทธ ๋ถ๋ถ์ด ์์ฒญ๋น ์ ํ ์๊ฐ ๊ตฌ์ฑ์ ์ง์ํ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง TimeoutException
๋ ์ง์ํด์ผ ํ๋ค๋ ์ฌ์ค์ ์์ง ๋ชปํ์ต๋๋ค.
์์ผ๋ก ์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๊ทธ๋งํ ๊ฐ์น๊ฐ ์๊ธฐ ๋๋ฌธ์ TaskCanceledException
๊ฐ ์๊ฐ ์ด๊ณผ ์ ๋ฐ์ํ์ฌ ํผ๋์ค๋ฝ์ต๋๋ค.
์ ๋ TaskCanceledExceptions
๊ฐ ์ด์ ์ง์ฅ์์ ์์ฐ ๋ฌธ์ ๋ฅผ ๋ค๋ฃฐ ๋ ํผ๋์ ์ฃผ์ ์์ธ์ด์๋ค๋ ๊ฒ์ ์ฆ๋ช
ํ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก HttpClient์ ๋ํ ํธ์ถ์ ๋ํํ๊ณ ์ ์ ํ ๊ฒฝ์ฐ TimeoutException์ ๋์ง๋๋ค.
@eiriktsarpalis ๊ฐ์ฌํฉ๋๋ค. ์ฐ๋ฆฌ๋ 5.0์์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ณํ์ด๋ฏ๋ก ์ํ๋ ๊ฒฝ์ฐ ํด๋น ๊ธฐ๊ฐ ๋ด์ ์ ํํ ์ ์์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ ํ์ ํฉ๋ฅํ์ต๋๋ค ๐.
์ผ๋ ? ๐ต .NET Core์ ์ฝ์๋ ๋ฏผ์ฒฉ์ฑ์ ์ด๋์ ์์ต๋๊น?
ํ๋์ ๋ฌธ์ ๋ก ์ ์ฒด ํ๋ก์ ํธ์ ๋ฏผ์ฒฉ์ฑ์ ํ๋จํ๋ ๊ฒ์ ๋ค์ ... ๋ถ๊ณตํํฉ๋๋ค.
์, ์ฝ๊ฐ ๋นํฉ์ค๋ฝ์ต๋๋ค. ์ฌ์ ํ ์ด ๋ฌธ์ ๊ฐ ์์ง๋ง ์์ ํ๊ธฐ ์ด๋ ต๊ณ (ํธํ์ฑ ์ํฅ์ผ๋ก) ๋จผ์ ํด๊ฒฐํด์ผ ํ ๋ ๋์ ์ฐ์ ์์์ ๋น์ฆ๋์ค ๋ชฉํ๊ฐ ์์์ต๋๋ค(๋คํธ์ํน์์). ์ญ์ฌ ์ ๋ฐ์ ๊ฑธ์ณ ์ด์ ํ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฐธ์กฐํ์ญ์์ค. ์ด ๋ฌธ์ ์.
BTW: ๋ค๋ฅธ ๋ง์ OSS ํ๋ก์ ํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก SLA๋ ETA ๋๋ ๋ฌธ์ ๊ฐ ์ธ์ ์์ ๋ ์ง์ ๋ํ ์ฝ์์ด ์์ต๋๋ค. ๋ชจ๋ ๊ฒ์ ์ฐ์ ์์, ๋ค๋ฅธ ์์ , ์ด๋ ค์ ๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ์ ๋ฌธ๊ฐ์ ์์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค.
ํ๋์ ๋ฌธ์ ๋ก ์ ์ฒด ํ๋ก์ ํธ์ ๋ฏผ์ฒฉ์ฑ์ ํ๋จํ๋ ๊ฒ์ ๋ค์ ... ๋ถ๊ณตํํฉ๋๋ค.
๋ญ, ์์งํ ์ง๋ฌธ์ด์๋ค. ๋ฒ์จ 2๋ ์ด ํ๋ ๊ณ ๋ 1๋ ์ด ๊ฑธ๋ฆฐ๋ค๋ ๊ฒ์ ๋ณด๊ณ ์กฐ๊ธ ๋๋์ต๋๋ค. ๊ทธ๋๋ ๊ณต๊ฒฉ์ ์๋ฏธ๊ฐ ์์ต๋๋ค ๐. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋จผ์ ๋ต๋ณํด์ผ ํ๋ ๋ช ๊ฐ์ง ์ง๋ฌธ์ด ์์์ต๋๋ค.
ํํ์ ์ธ๊ณ์์ ... ๋๋ ๊ทธ๊ฒ์ ์ข์ํ์ง ์์ง๋ง ์น์ ์์๋ ๋ ๋ค๋ฅธ ์ต์ ์ด ์์ต๋๋ค.
TaskCanceledException
๋ฅผ ๊ณ์ ๋์ง ์ ์์ง๋ง CancellationToken
๋ฅผ ์ผํธ๋ฆฌ ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
c#
catch(TaskCanceledException ex) when(ex.CancellationToken == HttpClient.TimeoutToken)
{
}
๊ทธ๋ฆฌ๊ณ ๋ ํ๋: TaskCanceledException
์์ ํ์๋ ์๋ก์ด HttpTimeoutException
๋ฅผ ๋์ง๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ํ๋:
TaskCanceledException
์์ ํ์๋ ์๋ก์ดHttpTimeoutException
๋ฅผ ๋์ง๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๋ชจ๋ ์ฐ๋ ค๋ฅผ ํด๊ฒฐํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํน์ ์๊ฐ ์ด๊ณผ๋ฅผ ์ฝ๊ฒ ํฌ์ฐฉํ ์ ์์ผ๋ฉฐ ์ฌ์ ํ TaskCanceledException
์ด๋ฏ๋ก ํ์ฌ ํด๋น ์์ธ๋ฅผ ํฌ์ฐฉํ๋ ์ฝ๋๋ ์ ์์ธ๋ ํฌ์ฐฉํฉ๋๋ค(์ค๋จ ๋ณ๊ฒฝ ์์).
๊ทธ๋ฆฌ๊ณ ๋ ํ๋: TaskCanceledException์์ ํ์๋ ์๋ก์ด HttpTimeoutException์ ๋์ง๋๋ค.
๋ค์ ๋ณด๊ธฐ ํํ์ง๋ง ์๋ง๋ ์ข์ ์ ์ถฉ์์ผ ๊ฒ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ํ๋:
TaskCanceledException
์์ ํ์๋ ์๋ก์ดHttpTimeoutException
๋ฅผ ๋์ง๋๋ค.๋๋ ๊ทธ๊ฒ์ด ๋ชจ๋ ์ฐ๋ ค๋ฅผ ํด๊ฒฐํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํน์ ์๊ฐ ์ด๊ณผ๋ฅผ ์ฝ๊ฒ ํฌ์ฐฉํ ์ ์์ผ๋ฉฐ ์ฌ์ ํ
TaskCanceledException
์ด๋ฏ๋ก ํ์ฌ ํด๋น ์์ธ๋ฅผ ํฌ์ฐฉํ๋ ์ฝ๋๋ ์ ์์ธ๋ ํฌ์ฐฉํฉ๋๋ค(์ค๋จ ๋ณ๊ฒฝ ์์).
์, ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ฌ๋๋ค์ด _๊ฐ๋ฅ_ํฉ๋๋ค.
try
{
// ...
}
catch (Exception ex) when (ex.GetType() == typeof(TaskCanceledException))
{
}
๋ฐ๋ผ์ ์ด๊ฒ์ ๊ธฐ์ ์ ์ผ๋ก ํ๊ธฐ์ ์ธ ๋ณ๊ฒฝ์ด ๋ ๊ฒ์ ๋๋ค.
๋ํ ๋๋ ๊ทธ๊ฒ์ด ๋ ์ธ๊ณ ๋ชจ๋์์ ์ฝ๊ฐ์ ์ต์
์ ์ํฉ์ ๊ฐ์ง๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ฌ์ ํ ๋ธ๋ ์ดํน ์ฒด์ธ์ง๊ฐ ์๋ ๋์์ ์ผ๋ฐ TimeoutException
๋ฅผ ์ป์ง ๋ชปํ ๊ฒ์
๋๋ค.
๊ธฐ์ ์ ์ผ๋ก ํ๊ธฐ์ ์ธ ๋ณ๊ฒฝ์ด ๋ ์ ์๋๋ก ์ด์ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ฌ๋๋ค์ด ์์ ์ ์์ต๋๋ค.
FWIW, ๊ฑฐ์ ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ด ๊นจ์ง ์ ์์ผ๋ฏ๋ก ์์ผ๋ก ์งํํ๋ ค๋ฉด ์ด๋๊ฐ์ ์ ์ ๊ทธ๋ ค์ผ ํฉ๋๋ค. corefx์์ ์ฐ๋ฆฌ๋ ๋ ํ์๋ ์ ํ์ ๋ฐํํ๊ฑฐ๋ ๋์ง๋ ๊ฒ์ ์ค๋จํ๋ ๊ฒ์ ๊ณ ๋ คํ์ง ์์ต๋๋ค.
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/breaking-change-rules.md#exceptions
ํํ์ ์ธ๊ณ์์ ... ๋๋ ๊ทธ๊ฒ์ ์ข์ํ์ง ์์ง๋ง ์น์ ์์๋ ๋ ๋ค๋ฅธ ์ต์ ์ด ์์ต๋๋ค.
TaskCanceledException
๋ฅผ ๊ณ์ ๋์ง ์ ์์ง๋งCancellationToken
๋ฅผ ์ผํธ๋ฆฌ ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.catch(TaskCanceledException ex) when(ex.CancellationToken == HttpClient.TimeoutToken) { }
๋๋ ์ด๊ฒ์ ์ ๋ง๋ก ์ข์ํ๋ค. "๋ชป์๊ฒผ๋ค""๋ ๊ฒ ์ธ์ ๋ค๋ฅธ ๋จ์ ์ด ์์ต๋๊น? ์ค๋ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ ๋ ex.CancellationToken
๋ ๋ฌด์์
๋๊น?
"๋ชป์๊ฒผ๋ค"๋ ๊ฒ ์ธ์ ๋ค๋ฅธ ๋จ์ ์ ์๋์?
๋๊ตฐ๊ฐ๊ฐ TimeoutToken์ด ์ ๋ฌ๋ ์ ์๊ณ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ ๋ ์ทจ์ ์ ํธ๋ก ์ฌ์ฉ๋ ์ ์๋ค๊ณ ์๊ฐํ๋ ๊ฒ์ ์ ๋ง ์ฌ์ธ ๊ฒ์ ๋๋ค. ์ด๋ ์ด๋ฌํ ์ฉ๋๋ก ๋ค๋ฅธ ๊ณณ์์ ์ฌ์ฉ๋๋ ๋์์ธ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋๋ ์ด๊ฒ์ ์ ๋ง๋ก ์ข์ํ๋ค. "๋ชป์๊ฒผ๋ค""๋ ๊ฒ ์ธ์ ๋ค๋ฅธ ๋จ์ ์ด ์์ต๋๊น? ์ค๋ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ ๋
ex.CancellationToken
๋ ๋ฌด์์ ๋๊น?
๋ฌธ์์์ ๋ช ์์ ์ผ๋ก ์ธ๊ธํ ์ ์๋ ํน์ ์์ธ ์ ํ์ ์ก๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ์ง๊ด์ ์ ๋๋ค.
๋๋ OperationCanceledException
๋ฐ ํ์ ์ ํ์ ๊ณ ๋ คํ์ฌ ์์ฉ ํ๋ก๊ทธ๋จ ์ค๋ฅ๊ฐ ์๋๋ผ ์ค๋จ๋ ์คํ์ ๋ํ๋ด๋ ๋ฐ ์ต์ํฉ๋๋ค. ์๊ฐ ์ด๊ณผ ์ HttpClient
์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ์ค๋ฅ์
๋๋ค. HTTP API์ ๋ํ ํธ์ถ์ด ์์๊ณ ์ฌ์ฉํ ์ ์์์ต๋๋ค. ์ด ๋์์ ์๋ฅผ ๋ค์ด ASP.NET Core ํ์ดํ๋ผ์ธ ๋ฏธ๋ค์จ์ด์์ ๋ ๋์ ์์ค์์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋์ ๋ณต์กํ๊ฒ ๋ง๋ญ๋๋ค. ์ด ์ฝ๋๋ OperationCanceledException
, error ๋ฐ not-error, ๋๋ ๋ชจ๋ HttpClient
ํธ์ถ์ throw-catch ๋ธ๋ก์ผ๋ก ๋ํํ๋๋ก ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ํ๋: TaskCanceledException์์ ํ์๋ ์๋ก์ด HttpTimeoutException์ ๋์ง๋๋ค.
๋ค์ ๋ณด๊ธฐ ํํ์ง๋ง ์๋ง๋ ์ข์ ์ ์ถฉ์์ผ ๊ฒ์ ๋๋ค.
๊ด๋ จ๋ ๋์์ธ ์ ์ฝ๊ณผ ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ ๊ณ ๋ ค ์ฌํญ์ ๊ณ ๋ คํ ๋ ์ ๋ง ์ถ์ ํ๊ฐ์? ์ด ์ค๋ ๋์ ๋๊ตฐ๊ฐ๊ฐ ๋จ์ ์ด ์๋ ๋ถ๋ช ํ ์ฐ์ํ ์๋ฃจ์ ์ ์ ์ํ๋ค๋ ๊ฒ์ ๋ชจ๋ฆ ๋๋ค(์ฌ์ฉ ๋๋ ๋์์ธ ์๋ ๋ฑ).
์ฐ๋ฆฌ๋ ์์ธ ์ ํ์ ๋ณ๊ฒฝํ๋ ๊ฒ๋ณด๋ค ์ด๊ฒ์ ๋ ์์ธํ ์ดํด๋ณด๊ณ ์ถ์ต๋๋ค. "์ด๋์์ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ต๋๊น?"๋ผ๋ ์ค๋ ๋ฌธ์ ๋ ์์ต๋๋ค. -- ์๋ฅผ ๋ค์ด, ์์ด์ด์ ๋๋ฌํ์ง ์์ ์ํ์์ ์์ฒญ์ด ์๊ฐ ์ด๊ณผ๋ ์ ์์ต๋๋ค -- ์ฐ๋ฆฌ๊ฐ ์ดํด๋ด์ผ ํ๊ณ ์๋ฃจ์ ์ ์ฐ๋ฆฌ๊ฐ ๊ฐ๋ ๋ฐฉํฅ๊ณผ ํธํ๋์ด์ผ ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์์ธ ์ ํ์ ๋ณ๊ฒฝํ๋ ๊ฒ๋ณด๋ค ์ด๊ฒ์ ๋ ์์ธํ ์ดํด๋ณด๊ณ ์ถ์ต๋๋ค. "์ด๋์์ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ต๋๊น?"๋ผ๋ ์ค๋ ๋ฌธ์ ๋ ์์ต๋๋ค. -- ์๋ฅผ ๋ค์ด, ์์ด์ด์ ๋๋ฌํ์ง ์์ ์ํ์์ ์์ฒญ์ด ์๊ฐ ์ด๊ณผ๋ ์ ์์ต๋๋ค -- ์ฐ๋ฆฌ๊ฐ ์ดํด๋ด์ผ ํ๊ณ ์๋ฃจ์ ์ ์ฐ๋ฆฌ๊ฐ ๊ฐ๋ ๋ฐฉํฅ๊ณผ ํธํ๋์ด์ผ ํฉ๋๋ค.
์ด๊ฒ์ด ์ ๋ง๋ก ๋น์ ์ด ์์์ผ ํ ์ฌํญ์
๋๊น? ์ค๋ฅ๊ฐ ๋ฐ์ํ ์์น์ ๋ฐ๋ผ ์ค๋ฅ๋ฅผ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ์๊ฒ ์ต๋๊น? ์ ์๊ฒ๋ ์ผ๋ฐ์ ์ผ๋ก ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์์ ์๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํฉ๋๋ค.
๋ ๋ง์ ์์
์ ์ํํ๊ณ ์ถ๋ค๋ฉด ์ด ๋ณ๊ฒฝ ์ฌํญ์ด ์ถ๊ฐ ์๊ตฌ ์ฌํญ์ผ๋ก ์ธํด .NET 5 ๊ธฐ์ฐจ๋ฅผ ๋์น๋ ๊ฒ์ ์ํ์ง ์์ต๋๋ค.wink:
@scalablecory ๊ฐ ์ ๊ธฐํ ๋ฌธ์ ๋ ์ฃผ๋ชฉํ ๋งํ๋ค๊ณ ์๊ฐํ์ง๋ง ์ด๊ฒ์ด ๋ ๋นจ๋ฆฌ ์์ ๋๋ ๊ฒ์ ๋ฐฉํดํด์๋ ์ ๋๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ์๊ฐ ์ด๊ณผ ์ด์ ๋ฅผ ํ๊ฐํ ์ ์๋๋ก ๋ฉ์ปค๋์ฆ์ ๊ฒฐ์ ํ ์ ์์ง๋ง ์ด์ ๋ํ ์์ธ ๋ฌธ์ ์์ ์ ์ง์ฐํ์ง ๋ง์ญ์์ค. ๋์ค์ ์ธ์ ๋ ์ง Reason
์์ฑ์ ์์ธ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
@thomaslevesque์ ๋์ํฉ๋๋ค. ๋๋ ์ ์ ๊ทธ๊ฒ์ ํฐ ๋ฌธ์ ๋ก ๋ค์ด ๋ณธ ์ ์ด ์์ต๋๋ค. ์ด๋์์ ์ค๋ ๊ฒ์ ๋๊น?
์ฝ๊ฐ์ ๋ช ์์ ์ธ ์กฐ์น๊ฐ ํ์ํ ์ด์ ๋ฅผ ํํค์ณ๋ ๊ด์ฐฎ์ ๋ฐ๋ฉด ์ผ๋ฐ ๊ฐ๋ฐ์์ ๊ฒฝ์ฐ ํ ๊ฐ์ง ์ฒ๋ฆฌ์ ๋ํด ์๊ณ /๊ด๋ฆฌํด์ผ ํ๋ ๊ฝค ํ์ ๋๋ฒ๊น ์ฌ๋ก์ ๋๊น?
์ฐ๋ฆฌ๋ ์์ธ ์ ํ์ ๋ณ๊ฒฝํ๋ ๊ฒ๋ณด๋ค ์ด๊ฒ์ ๋ ์์ธํ ์ดํด๋ณด๊ณ ์ถ์ต๋๋ค. "์ด๋์์ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์ต๋๊น?"๋ผ๋ ์ค๋ ๋ฌธ์ ๋ ์์ต๋๋ค. -- ์๋ฅผ ๋ค์ด, ์์ด์ด์ ๋๋ฌํ์ง ์์ ์ํ์์ ์์ฒญ์ด ์๊ฐ ์ด๊ณผ๋ ์ ์์ต๋๋ค -- ์ฐ๋ฆฌ๊ฐ ์ดํด๋ด์ผ ํ๊ณ ์๋ฃจ์ ์ ์ฐ๋ฆฌ๊ฐ ๊ฐ๋ ๋ฐฉํฅ๊ณผ ํธํ๋์ด์ผ ํฉ๋๋ค.
์ฌ๊ธฐ์ ์๋ฏธํ๋ ๋ฐ๋ HttpClient๊ฐ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๊ฒ๋ณด๋ค ์ฌ๋ฐ๋ฅธ ์๊ฐ ์ด๊ณผ ์์ธ ์ ํ์ ๋ฐ์์ํค๋ ๊ฒ์ด ๊ฐ HttpMessageHandler์ ์ฑ ์์ด์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ์ ์๋ฏธํ๋ ๋ฐ๋ HttpClient๊ฐ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๊ฒ๋ณด๋ค ์ฌ๋ฐ๋ฅธ ์๊ฐ ์ด๊ณผ ์์ธ ์ ํ์ ๋ฐ์์ํค๋ ๊ฒ์ด ๊ฐ HttpMessageHandler์ ์ฑ ์์ด์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค.
์ค๋๋ ์ ์๋ ์ถ์ํ๋ก ๊ทธ๊ฒ์ด ์ด๋ป๊ฒ ๊ฐ๋ฅํ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. HttpMessageHandler๋ HttpClient์ ์๊ฐ ์ด๊ณผ์ ๋ํด ์์ง ๋ชปํฉ๋๋ค. HttpMessageHandler์ ๊ดํ ํ, ํธ์ถ์์ ์ทจ์ ํ ํฐ ์ ํธ, HttpClient์ CancelPendingRequests ํธ์ถ, HttpClient์ ๊ฐ์ ์ ํ ์๊ฐ ๋ง๋ฃ ๋ฑ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก ์ทจ์ ์์ฒญ์ด ์์ ์ ์๋ ์ทจ์ ํ ํฐ์ ์ ๋ฌํ์ต๋๋ค.
์ด๊ฒ์ด ์ ๋ง๋ก ๋น์ ์ด ์์์ผ ํ ์ฌํญ์ ๋๊น? ์ค๋ฅ๊ฐ ๋ฐ์ํ ์์น์ ๋ฐ๋ผ ์ค๋ฅ๋ฅผ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ์๊ฒ ์ต๋๊น? ์ ์๊ฒ๋ ์ผ๋ฐ์ ์ผ๋ก ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ์์ ์๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํฉ๋๋ค.
์๋ฒ๊ฐ ๊ทํ์ ์์ฒญ์ ์ฒ๋ฆฌํ๋์ง ์๋ ๊ฒ์ด ์ ์ฉํฉ๋๋ค. ์ง๋จ์๋ ์ข์ต๋๋ค. ์๊ฒฉ ์๋ฒ๊ฐ ์๊ฐ ์ด๊ณผ๋์ง๋ ์์ง๋ง ํด๋ผ์ด์ธํธ๊ฐ ์๊ฐ ์ด๊ณผ๋ฅผ ๋ณด๊ณ ํ๋ ๊ฒ์ ์ค๋ง์ค๋ฌ์ด ๊ฒฝํ์ ๋๋ค.
@davidsh ๋ ๋ ๋ง์ ํต์ฐฐ๋ ฅ์ ๊ฐ์ง ์ ์์ต๋๋ค.
@thomaslevesque์ ๋์ํฉ๋๋ค. ๋๋ ์ ์ ๊ทธ๊ฒ์ ํฐ ๋ฌธ์ ๋ก ๋ค์ด ๋ณธ ์ ์ด ์์ต๋๋ค. ์ด๋์์ ์ค๋ ๊ฒ์ ๋๊น?
์ต๊ทผ NCL ํ์์์ ์ ๊ธฐ๋ ๋ฌธ์ ์ ๋๋ค. ์ด๊ฒ์ด ์ผ์ ํญ๋กํ๊ฑฐ๋ ์ง์ฐ์ํฌ ๋งํผ ์ค์ํ์ง ์๋ค๊ณ ๊ฒฐ์ ํ ์๋ ์์ง๋ง ๋จผ์ ๋น ๋ฅธ ํ ๋ก ์ ๊ฐ์น๊ฐ ์์ต๋๋ค.
@dotnet/ncl @stephentoub ์ด๊ฑธ ์นจ๋์ ๋๋์. ์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ๊ฐ ํ๋ ๋ชจ๋ ๊ฒ์ด ๋ฏธ๋ฌํ๊ฒ ๋ฌด๋์ง ๊ฒ์ด๋ผ๋ ๊ฒ์ ์๋๋ค. ์ด๊ฒ์ ์ต์ ์ ์ ํ์ฒ๋ผ ๋ณด์ ๋๋ค. ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์์ผ๋ก ๋์๊ฐ ๊ฒ์ ์ ์ํฉ๋๋ค.
TaskCanceledException
์์ ํ์๋ ์๋ก์ดHttpTimeoutException
๋ฅผ ๋์ง๋๋ค.
๋ฐ๋?
TaskCanceledException์์ ํ์๋ ์๋ก์ด HttpTimeoutException์ ๋์ง๋๋ค.
์ค์ ๋ก ์ด๋ป๊ฒ ํฉ๋๊น? ์๋ง๋ ์ฝ๋๋ฅผ ์คํฌ๋ฌ๋นํ๊ณ CancellationToken.ThrowIfCancellationRequested ๋ฅผ ํธ์ถํ๋ ๋ชจ๋ ์์น๋ฅผ ์ฐพ์ ๋ค์์ผ๋ก ๋ณํํด์ผ ํจ์ ์๋ฏธํฉ๋๋ค.
c#
if (token.IsCancellationRequested) throw new HttpTimeoutException(EXTRASTUFF, token);
๋ฟ๋ง ์๋๋ผ ์ฐ๋ฆฌ๊ฐ ์ค์ ๋ก OperationCancelledException
๋ฅผ ํธ์ถํ ์๋ ์๋ ๋ช
์์ ์ฅ์๋ ์์ต๋๋ค.
์ด์จ๋ ๋ชจ๋ ๊ด๋ จ ์ฝ๋๋ฅผ ๊ฒํ ํ ํ์๊ฐ ์๋ ์ต์ ์ด ์์ต๋๊น?
์ด์จ๋ ๋ชจ๋ ๊ด๋ จ ์ฝ๋๋ฅผ ๊ฒํ ํ ํ์๊ฐ ์๋ ์ต์ ์ด ์์ต๋๊น?
์๋ง๋ ์๋ ์๋ ์์ง๋ง ์ฐ๋ฆฌ๊ฐ ์ ์ดํ์ง ์๋ ๊ณณ์ด ์์ ์ ์์ต๋๋ค(์์ง ํ์คํ์ง ์์). ๋ฐ๋ผ์ ์ ์ฌ์ ์ผ๋ก ์์์ TaskCancelledException/OperationCancelledException์ ์ก๊ณ ์๋ก์ด HttpTimeoutException์ ๋ค์ ๋ฐ์์์ผ์ผ ํฉ๋๋ค.
์๋ง๋ ์ฝ๋๋ฅผ ์คํฌ๋ฌ๋นํ๊ณ CancellationToken.ThrowIfCancellationRequested๋ฅผ ํธ์ถํ๋ ๋ชจ๋ ์์น๋ฅผ ์ฐพ์ ๋ค์์ผ๋ก ๋ณํํด์ผ ํจ์ ์๋ฏธํฉ๋๋ค.
์ด์จ๋ ๋ชจ๋ ๊ด๋ จ ์ฝ๋๋ฅผ ๊ฒํ ํ ํ์๊ฐ ์๋ ์ต์ ์ด ์์ต๋๊น?
์ ํํ.
ํธ๋ค๋ฌ์ ๊ดํ ํ ๊ทธ๋ค์ด ๋ฐ๋ ๋ชจ๋ ๊ฒ์ CancellationToken์ ๋๋ค. ๊ทธ๋ค์ ๊ทธ ํ ํฐ์ด ์ด๋์ ์๋์ง, ๋๊ฐ ์์ฑํ๋์ง ๋๋ ์ทจ์๋ฅผ ์์ฒญํ์ ์ ์๋ ์ด์ ๋ฅผ ์์ง ๋ชปํ๊ณ ์ ๊ฒฝ ์ฐ์ง ์์ต๋๋ค. ๊ทธ๋ค์ด ์๋ ๊ฒ์ ์ด๋ค ์์ ์์ ์ทจ์๊ฐ ์์ฒญ๋ ์ ์๊ณ ์๋ต์ผ๋ก ์ทจ์ ์์ธ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ํธ๋ค๋ฌ์์ ํ ์ผ์ด ์์ต๋๋ค.
๊ด๋ จ CancellationTokenSource๋ฅผ ๋ง๋ค๊ณ ์๊ฐ ์ด๊ณผ๋ฅผ ์ค์ ํ๋ ๊ฒ์ HttpClient ์์ฒด์
๋๋ค.
https://github.com/dotnet/corefx/blob/bdd33976fe3713cc3e78b83cf2a1176c70b793be/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L488
ํ์์์์ ์ ์ ์ผ๋ก HttpClient ์์ฒด์ ๋ฐ๋ช
์ด๋ฉฐ ํน๋ณํ ๊ฒ์ผ๋ก ๋ํ๋ ์ทจ์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ ๊ฒ์ธ์ง ์ฌ๋ถ๋ง ์ ์ ์์ต๋๋ค.
์ฆ, ์์์ ์ฐธ์กฐํ ์ฝ๋๋ ๋ณ๋์ CancellationTokenSource๋ก ๋๋ ์์ฒด์ ์ผ๋ก ์๊ฐ ์ด๊ณผ ๋ ผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ๊ณ CTS๋ฅผ ์ทจ์ํ๋ ๊ฒ ์ธ์๋ ์๊ฐ ์ด๊ณผ๋ฅผ ๋ณ๋๋ก ์ถ์ ํ๋๋ก ๋ฆฌํฉํ ๋งํด์ผ ํ๋ฉฐ ๋ํ ๋ค์์ ์ํํ ์ ์๋ ํ๋๊ทธ๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์๋ ํ์ธํ์ญ์์ค. ์ฌ๊ธฐ์ ์ถ๊ฐ ํ ๋น์ ์ถ๊ฐํ ๊ฒ์ด๋ผ๋ ์ ์์ ์ด๊ฒ์ ์ ๋ฃ๊ฐ ์๋ ๊ฐ๋ฅ์ฑ์ด ๋์ง๋ง ์ฝ๋ ๊ด์ ์์๋ ๋น๊ต์ ๊ฐ๋จํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ HttpClient์ ๋ค์๊ณผ ๊ฐ์ ์์น์ ์์ต๋๋ค.
https://github.com/dotnet/corefx/blob/bdd33976fe3713cc3e78b83cf2a1176c70b793be/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L536 -L541
๊ทธ๋ฆฌ๊ณ
https://github.com/dotnet/corefx/blob/bdd33976fe3713cc3e78b83cf2a1176c70b793be/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L562 -L566
์์ธ๋ฅผ ํฌ์ฐฉํ๋ฉด ํน๋ณํ ๊ฒฝ์ฐ ์ทจ์๋ฅผ ์ํํ์ฌ ์๊ฐ ์ด๊ณผ๊ฐ ๋ง๋ฃ๋์๋์ง ํ์ธํ๊ณ ๋ง๋ฃ๋ ๊ฒฝ์ฐ ์ทจ์์ ์์ธ์ด๋ผ๊ณ ๊ฐ์ ํ๊ณ ์ํ๋ ์ ํ์ ์ ์์ธ๋ฅผ throwํด์ผ ํฉ๋๋ค.
์ ํ ์๊ฐ์ด ๋ง๋ฃ๋์๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ ๋ง๋ฃ๋ ๊ฒฝ์ฐ ์ทจ์์ ์์ธ์ด๋ผ๊ณ ๊ฐ์ ํ๊ณ ์ํ๋ ์ ํ์ ์ ์์ธ๋ฅผ throwํ๋ ค๋ฉด ํน์ํ ๊ฒฝ์ฐ ์ทจ์๊ฐ ํ์ํฉ๋๋ค.
HttpClient.Timeout ์์ฑ์ด ๊ด๋ จ๋์ง ์์ ๊ฒฝ์ฐ ์ด๊ฒ์ ์ด๋ป๊ฒ ์๋ํฉ๋๊น? ์๋ง๋ "๋ฌดํ"์ผ๋ก ์ค์ ๋์ด ์์ ๊ฒ์ ๋๋ค. HttpClient API(GetAsync, SendAync ๋ฑ)์ ์ง์ ์ ๋ฌ๋ ์ทจ์ ํ ํฐ์ ์ด๋ป์ต๋๊น? ๋๋ ๊ทธ๊ฒ์ด ๋๊ฐ์ด ์๋ํ๋ค๊ณ ๊ฐ์ ํฉ๋๊น?
HttpClient.Timeout ์์ฑ์ด ๊ด๋ จ๋์ง ์์ ๊ฒฝ์ฐ ์ด๊ฒ์ ์ด๋ป๊ฒ ์๋ํฉ๋๊น?
์ง๋ฌธ์ ์ดํดํ์ง ๋ชปํ๊ฒ ์ต๋๋ค... ์ฌ๊ธฐ์ ๋งํ๋ ์ ์ผํ ์๊ฐ ์ ํ์
๋๋ค. ๋ฌดํ์ผ๋ก ์ค์ ํ๋ฉด ์ด ์๊ฐ ์ด๊ณผ๋ก ์ธํด ์ทจ์๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉฐ ํ ์ผ์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฏธ ํน์ํ ๊ฒฝ์ฐ Timeout == Infinite์ด๋ฉฐ ๊ณ์ํด์ ๋ค์์ ์ํํฉ๋๋ค.
https://github.com/dotnet/corefx/blob/bdd33976fe3713cc3e78b83cf2a1176c70b793be/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L481
HttpClient API(GetAsync, SendAync ๋ฑ)์ ์ง์ ์ ๋ฌ๋ ์ทจ์ ํ ํฐ์ ์ด๋ป์ต๋๊น? ๋๋ ๊ทธ๊ฒ์ด ๋๊ฐ์ด ์๋ํ๋ค๊ณ ๊ฐ์ ํฉ๋๊น?
์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ ์์ ์ด ๋ง๋ ํ ํฐ ์ค ํ๋๋ก ์ ๋ฌ๋ ๋ชจ๋ ํ ํฐ์ ๊ฒฐํฉํฉ๋๋ค.
https://github.com/dotnet/corefx/blob/bdd33976fe3713cc3e78b83cf2a1176c70b793be/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L485
์ด์ ์๊ฒฌ์์ ์ธ๊ธํ๋ฏ์ด HttpClient.Timeout์ ๋ํ ์์ฒด ์ฒ๋ฆฌ๋ฅผ ์ถ์ ํฉ๋๋ค. ํธ์ถ์๊ฐ ์๊ฐ ์ด๊ณผ๋ก ๊ตฌ์ฑํ ํ ํฐ์ ์ ๋ฌํ๊ธฐ๋ก ์ ํํ ๊ฒฝ์ฐ ์ด๋ฅผ ํน๋ณํ ์ฒ๋ฆฌํ๋ ๊ฒ์ ํธ์ถ์์๊ฒ ๋ฌ๋ ค ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์๊ฐํ๋ ํ ๊ทธ๊ฒ์ ์ทจ์ ์์ฒญ์ผ ๋ฟ์
๋๋ค.
๋ฐ๋?
๋ด๋ถ ์์ธ๋ก TimeoutException์ ๋ํํ๋ ์ทจ์ ์์ธ๋ฅผ throwํ๋ ๋์ ๊ธฐ์กด TimeoutException๊ณผ "๊ฒฝ์ํ๋" ์๋ก์ด ํ์ ์์ธ ์ ํ์ ๋์ ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ๋ชฉํ๊ฐ ์๋น์๊ฐ ์ทจ์๊ฐ ์๊ฐ ์ด๊ณผ๋ก ์ธํ ๊ฒ์ธ์ง ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ๊ฒฐ์ ํ ์ ์๋๋ก ํ๋ ๊ฒ์ด๋ผ๋ฉด ์ถฉ๋ถํ ๊น์? ์๋ก์ด ํ๋ฉด์ ์ ํ์๋ก ํ์ง ์๊ณ ๋์ผํ ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ผ ๊ฒ์ ๋๋ค.
๋ด๋ถ ์์ธ๋ก TimeoutException์ ๋ํํ๋ ์ทจ์ ์์ธ๋ฅผ ๋์ง๋ ๋์ ๊ธฐ์กด TimeoutException๊ณผ "๊ฒฝ์ํ๋" ์๋ก์ด ํ์ ์์ธ ์ ํ์ ๋์ ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
ํธ์์ ๋๋ถ๋ถ. ์ฐ๊ธฐ๊ฐ ๋ ์ฝ๊ณ ์ง๊ด์ ์ ๋๋ค.
catch(HttpTimeoutException)
~๋ณด๋ค
catch(OperationCanceledException ex) when (ex.InnerException is TimeoutException)
์ฆ, ์๊ฐ ์ด๊ณผ๋ฅผ ์๋ณํ๊ธฐ๊ฐ ํฉ๋ฆฌ์ ์ผ๋ก ์ฌ์ด ํ ์ด๋ ์ชฝ์ด๋ ๊ด์ฐฎ์ต๋๋ค.
TimeoutException์ ๋ด๋ถ ์์ธ๋ก ๋ํํ๋ ์ทจ์ ์์ธ๋ฅผ ๋์ง๊ณ ์์ต๋๊น?
์ข์ ํํ์ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฌํ ์ข ๋ฅ์ ์๊ฐ ์ด๊ณผ๋ฅผ ์ฒ๋ฆฌํ ๋ ๊ฐ์ฅ ํฐ ๊ณจ์นซ๊ฑฐ๋ฆฌ์๋ ์์ธ ๋ก๊ทธ๋ฅผ โโ๋ช ํํ๊ฒ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ๋ํ ๊ธฐ๋ณธ ์ฒ๋ฆฌ๊ธฐ์ ์ํด ๋ฐ์ํ๋ ์๊ฐ ์ด๊ณผ๊ฐ ์๋๋ผ ์์ฒญ์ ์ทจ์ํ๋ HttpClient๋ผ๋ ์ฌ์ค์ ๋ ์ ์ ๋ฌํ ์ ์์ต๋๋ค. ๋ํ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๋ค.
๋ถ๋ฅ:
InnerException
์ TimeoutException
๊ฐ ๋๋๋ก ์
๋ฐ์ดํธํ๊ณ ์๊ฐ ์ด๊ณผ ํธ๋ฆฌ๊ฑฐ๋ก ์ธํ ์ทจ์๋ฅผ ์ฝ๊ฒ ๊ตฌ๋ณํ๋ ๋ก๊น
/์ง๋จ์ฉ ๋ฉ์์ง๋ฅผ ํ์ํฉ๋๋ค.TimeoutException
ํ์ธ, ๋ฌดํ Timeout
$ ์ฌ์ฉ, ์๊ฐ ์ด๊ณผ ๊ธฐ๊ฐ์ด ์๋ CancellationToken
์ ๋ฌ ๋ฑ์ฌ๊ธฐ์์ ํด๊ฒฐํ๋ ค๋ฉด ์ฝ๊ฐ์ ํํ์ด ํ์ํ๋ฉฐ ์ด๊ฒ์ด ๊ธฐ์กด ์ฝ๋์ ์ฐ์ํ ์์ค์ ํธํ์ฑ์ ์ ๊ณตํ ๊ฒ์ด๋ผ๊ณ ๋ฏฟ์ต๋๋ค.
๋ด๋ถ ์์ธ๋ก TimeoutException์ ๋ํํ๋ ์ทจ์ ์์ธ๋ฅผ ๋์ง๋ ๋์ ๊ธฐ์กด TimeoutException๊ณผ "๊ฒฝ์ํ๋" ์๋ก์ด ํ์ ์์ธ ์ ํ์ ๋์ ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
ํธ์์ ๋๋ถ๋ถ. ์ฐ๊ธฐ๊ฐ ๋ ์ฝ๊ณ ์ง๊ด์ ์ ๋๋ค.
catch(HttpTimeoutException)
~๋ณด๋ค
catch(OperationCanceledException ex) when (ex.InnerException is TimeoutException)
์ฆ, ์๊ฐ ์ด๊ณผ๋ฅผ ์๋ณํ๊ธฐ๊ฐ ํฉ๋ฆฌ์ ์ผ๋ก ์ฌ์ด ํ ์ด๋ ์ชฝ์ด๋ ๊ด์ฐฎ์ต๋๋ค.
@scalablecory ๋ช ์๊ฐ ๋์ ํ ๋ก ์ ๋์น ๊ฒ ๊ฐ์ ๋ถ๋๋ฝ์ต๋๋ค. ์ผ๋ฐ LoB .NET ๊ฐ๋ฐ์์ ์ด๋ฌํ ์ ํ์ ์์ฌ ์ํต์ ํ ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ํ์๋ HttpTimeoutException์ ์ก๋ ๊ฒ์ด ์ฌ๋๋ค์ด ์ดํด/์ฑํํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ์ฝ์ต๋๋ค. ๋ด๋ถ ์์ธ์ ์์ธ ํํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ธฐ์ตํ์ญ์์ค. ๋ชจ๋ ์ฌ๋์ด ์์ธ ํํฐ๊ฐ ๋ฌด์์ธ์ง์กฐ์ฐจ ์์ง ๋ชปํฉ๋๋ค.
๋์์, ๋๋ ์ด๊ฒ์ด ๋น์ ์ด ๋งํ๋ฏ์ด ํ์คํ ์น/ํ๊ฒฐ ์๋ฃจ์ ์ด ์๋ ์๋๋ฆฌ์ค ์ค ํ๋๋ผ๋ ๊ฒ์ ์์ ํ ์๊ณ ์์ต๋๋ค.
@ericsampson ์ด๋ผ๋ ์ ์ ๋์ํ์ง๋ง ์ด๋ ๋ง์ ๊ธฐ์กด ์ฌ์ฉ์์๊ฒ ํฐ ๋ณํ๊ฐ ๋ ๊ฒ์ ๋๋ค. @scalablecory ๊ฐ ์ธ๊ธํ๋ฏ์ด ํธํ์ฑ ์์์ ์ ํํ๋ฉด์ ๊ฐ์ ์ ์ํด ํํํ์ต๋๋ค.
์์ธ์ ๋ํด ์๊ฐํ ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ํ ๋ฐฉ์์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค. OperationCanceledException์์ ์์ธ๋ฅผ ํ์์ํค๋ฉด ์ด๋ฌํ ์์ธ๋ฅผ ๋น๋๊ธฐ์ ์ฌ์ฉ์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ์ง์ด ๊ทธ๊ฒ์ ์์ ์ ๋นก๋นกํฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๊ณผ๊ฑฐ์ ๋ณด์๋ฏ์ด ๋น๋๊ธฐ ์ ๊ทผ ๋ฐฉ์์ ๋ช ๊ฐ์ง ์งํ๊ฐ ์์๊ณ ์์ ์ ๊ตฌํ ์ธ๋ถ ์ฌํญ์ผ๋ก ๊ฐ์ฃผํ์ง๋ง ์๋ฅผ ๋ค์ด TimeoutException์ ๋ณ๊ฒฝ๋์ง ์๋ ์์ผ ๊ฐ๋ ์ ์ผ๋ถ์ ๋๋ค.
@ericsampson ์ด๋ผ๋ ์ ์ ๋์ํ์ง๋ง ์ด๋ ๋ง์ ๊ธฐ์กด ์ฌ์ฉ์์๊ฒ ํฐ ๋ณํ๊ฐ ๋ ๊ฒ์ ๋๋ค. @scalablecory ๊ฐ ์ธ๊ธํ๋ฏ์ด ํธํ์ฑ ์์์ ์ ํํ๋ฉด์ ๊ฐ์ ์ ์ํด ํํํ์ต๋๋ค.
๋ด๊ฐ ๋ฐ๋์ ๋ํ ์ต์ ์ ๋์ํ์ง ์๋ ๊ฒ์ ์๋์ง๋ง - ๋ด๊ฐ ์ดํดํ ํ - ๋ฌธ์ ๋ ํ์ ์ต์ ์ด ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋๋ผ ๋ํ ์ต์ ์ด ๋ ๊ฐ๋จํ๋ค๋ ์ ์ ์ง์ ํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ ๋ก ์ ์๋ถ๋ถ์์ @stephentoub๊ฐ ์ธ๊ธํ๋ฏ์ด ํ์๋ ์์ธ๋ฅผ throwํ๋ ๊ฒ์ corefx ์ง์นจ์ ๋ฐ๋ผ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ผ๋ก ๊ฐ์ฃผ๋์ง ์์ต๋๋ค.
TaskCanceledException์์ HttpTimeoutException์ ํ์์ํค๋ ๊ฒ์ ์ด ๋ ์์ธ ์ฌ์ด์ "is a" ๊ด๊ณ๋ฅผ ์๋ฐํฉ๋๋ค. HttpTimeoutException์ ํน๋ณํ ์ฒ๋ฆฌํ์ง ์๋ ํ ์ฌ์ ํ ์ทจ์๊ฐ ๋ฐ์ํ๋ค๊ณ ์๊ฐํ๋๋ก ํธ์ถ ์ฝ๋๋ฅผ ๋ง๋ญ๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์๊ฐ ์ด๊ณผ์ธ์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ ์ํด ์ทจ์ ํ ํฐ์ด ์ทจ์๋์๋์ง ํ์ธํ๋ ์๊ฐ์ ์ํํด์ผ ํ๋ ๊ฒ๊ณผ ๋์ผํ ์ฒ๋ฆฌ์
๋๋ค. ๊ฒ๋ค๊ฐ ์ฝ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ ๊ฐ์ ํ์์์ ์์ธ๊ฐ ์๋ ๊ฒ์ ํผ๋์ค๋ฝ์ต๋๋ค.
TaskCanceledException์ ๋ด๋ถ ์์ธ๋ก TimeoutException์ ์ถ๊ฐํ๋ฉด ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ง ์์ต๋๋ค. ์ด๋ฏธ ์ทจ์ ํ ํฐ์ ํ์ธํ๊ณ ์๊ฐ ์ด๊ณผ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ ์ผํ ํฉ๋ฆฌ์ ์ธ ํด๊ฒฐ์ฑ ์ ์๊ฐ ์ด๊ณผ ์ ๋ฐ์ํ ์์ธ๋ฅผ TimeoutException์ผ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ๋๋ค. ์, ๊ทธ๊ฒ์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ๋ ๊ฒ์ด์ง๋ง ๋ฌธ์ ๋ ์ด๋ฏธ ์ฌ๋ฌ ์ฃผ์ ๋ฆด๋ฆฌ์ค์ ๊ฑธ์ณ ์์ผ๋ฉฐ ์ฃผ์ ๋ฆด๋ฆฌ์ค์ ๋ชฉ์ ์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋๋ค.
๊ธฐ์กด ๋ฒ์ ์ ๋ํ ๋ฌธ์๋ฅผ ์
๋ฐ์ดํธํ์ฌ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ ๋ ๋ฉ์๋๊ฐ TaskCanceledException
๋ฐ/๋๋ OperationCanceledException
(๋ ๊ตฌ์ฒด์ ์ธ ์ ํ ๋ชจ๋ ๊ฐ๋ฅ์ฑ์ด ์๋ ๊ฒ์ผ๋ก ๋ํ๋จ)์ throwํ ์ ์์์ ๋ํ๋ผ ์ ์์ต๋๊น? ํ์ฌ ๋ฌธ์์๋ HttpRequestException
๊ฐ ์๊ฐ ์ด๊ณผ๋ฅผ ์ฒ๋ฆฌํ๋ค๊ณ ๋์ ์๋๋ฐ ์ด๋ ์ฌ๋ฐ๋ฅด์ง ์๊ณ ์คํด์ ์์ง๊ฐ ์์ต๋๋ค.
@qidydl ์ด ๊ณํ์ ๋๋ค... ์๊ฐ ์ด๊ณผ๊ฐ ๋ํ๋ ์ ์๋ ๋ชจ๋ ๋ฐฉ๋ฒ๊ณผ ์ด๋ฅผ ์์ธํ ์ค๋ช ํ๋ ๋ฐฉ๋ฒ์ ์์ ํ ๋ฌธ์ํํฉ๋๋ค.
@alnikola , @scalablecory , @davidsh , @karelz , ๊ทธ๋ฆฌ๊ณ ์ด ํ ๋ก /๊ตฌํ์ ์ฐธ์ฌํ ๋ชจ๋ ์ฌ๋๋ค์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ ๋ง ๊ฐ์ฌํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
@karelz ๋ ์ด ์คํด์ ์์ง๊ฐ ์๋ ์์ธ์ ์ํฅ์ ๋ฐ๋ ๋ค๋ฅธ ๊ณ ๊ฐ์ผ๋ก ๋ฉ๋ชจ๋ฅผ ์ถ๊ฐํ๊ณ ์์ต๋๋ค. :)