C#에서 HttpClient를 활용해 비동기 웹 요청을 해보도록 하겠습니다.
지난 포스팅 중 Line notify 를 보내는 예제를 활용해 보도록하겠습니다.
HttpClient로 LINE알림 비동기로 호출해보기
아래 코드는 비동기로 라인 메시지를 보내는 코드입니다.
Header설정은 DefaultRequestHeaders.add()를 통해 name, value를 각각 추가해줍니다.
Post 호출의 경우 파라미터를 같이 Dictionary<string,string> 형태로 저장을 해준 뒤,
FormUrlFormUrlEncodedContent 객체 생성시 파라미터로 전달해줍니다.
최종적으로 PostAsync("url", "전달할내용") 메소드를 호출해 줍니다.
PostAsync 호출시에는 await 키워드를 넣어줘야 리턴값을 확인해 줄 수 있습니다.
public static async Task<HttpResponseMessage> PostAsyncHttp()
{
HttpClient _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer Ask2OVGx4Jm9mUvcSLmfv1nY");
var parameters = new Dictionary<string, string>();
parameters.Add("message", "안녕하세요");
var encodedContent = new FormUrlEncodedContent(parameters);
var response = await _httpClient.PostAsync("https://notify-api.line.me/api/notify", encodedContent).ConfigureAwait(false);
return response;
}
위 메소드를 비동기로 라인메시지 보내는 API를 3번 연속 호출한 후 비동기 메소드가 처리되는 동안 거의 동시에
FOR문을 수행하는 코드를 작성해보겠습니다.
비동기 메소드 내부에 Console.WriteLine()을 찍어 수행여부를 확인해 주도록 했습니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTest
{
class Program
{
static async Task Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Console.WriteLine("비동기 3회 시작");
Task<HttpResponseMessage> first = PostAsyncHttp();
Task<HttpResponseMessage> second = PostAsyncHttp();
Task<HttpResponseMessage> third = PostAsyncHttp();
for(int i = 0; i < 10; i++)
{
Console.WriteLine("다른 로직 수행 : " + i);
}
HttpResponseMessage fr = await first;
HttpResponseMessage sec = await first;
HttpResponseMessage th = await first;
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds+"ms");
Thread.Sleep(5000);
}
public static async Task<HttpResponseMessage> PostAsyncHttp()
{
HttpClient _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer Ask2O1C1EUq0iNdBGAVGx4Jm9mUvcSLmfvgV61OH1nY");
var parameters = new Dictionary<string, string>();
parameters.Add("message", "안녕하세요");
var encodedContent = new FormUrlEncodedContent(parameters);
var response = await _httpClient.PostAsync("https://notify-api.line.me/api/notify", encodedContent).ConfigureAwait(false);
Console.WriteLine("비동기 PostAsyncHttp() 호출");
return response;
}
}
}
실행결과 비동기 메소드를 3번 요청한 후 for문을 수행하는 동안 각 비동기 메소드들이 호출된 모습입니다.
라인 메시지도 3건이 온 것을 확인 할 수 있습니다.
1회 호출과 3회 비동기 호출 수행시간 비교하기
3개의 비동기 메소드 포함 전체 로직 수행시간이 729ms인 것을 확인 할 수 있는데요.
비동기 메소드 1회 실행시의 수행 시간과 한 번 비교해 보겠습니다.
2개 메소드의 주석을 치고 1번만 호출해보겠습니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTest
{
class Program
{
static async Task Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Console.WriteLine("비동기 3회 시작");
Task<HttpResponseMessage> first = PostAsyncHttp();
//Task<HttpResponseMessage> second = PostAsyncHttp();
//Task<HttpResponseMessage> third = PostAsyncHttp();
for(int i = 0; i < 10; i++)
{
Console.WriteLine("다른 로직 수행 : " + i);
}
HttpResponseMessage fr = await first;
//HttpResponseMessage sec = await first;
//HttpResponseMessage th = await first;
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds+"ms");
Thread.Sleep(5000);
}
public static async Task<HttpResponseMessage> PostAsyncHttp()
{
HttpClient _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer Ask2O1C1EUq0iNdBGAVGx4Jm9mUvcSLmfvgV61OH1nY");
var parameters = new Dictionary<string, string>();
parameters.Add("message", "안녕하세요");
var encodedContent = new FormUrlEncodedContent(parameters);
var response = await _httpClient.PostAsync("https://notify-api.line.me/api/notify", encodedContent).ConfigureAwait(false);
Console.WriteLine("비동기 PostAsyncHttp() 호출");
return response;
}
}
}
실행시간이 770ms인 것을 확인 할 수 있습니다. 여러번 프로그램을 다시 빌드해봐도 비슷한 시간이 측정됩니다.
3회 호출 했을때와 거의 차이가 없는 것을 알 수 있습니다.
동기식 실행시에는 1회 수행결과 * 3배의 수행시간이 걸리는 것에 비해
비동기 요청으로 처리 할 경우 1/3로 실행시간을 줄일 수 있습니다.
10회 호출과 비교하기
10번을 비동기로 요청해보겠습니다.
10번의 메소드를 요청해놓고 다음 코드 실행을 위해 기다리지 않기 때문에,
시간차이는 요청로직을 수행하는 정도의 차이만 발생하는 것을 알 수 있습니다.
코드 스니펫 복사
Task.WhenAll를 활용해 비동기 메소드 호출 결과 처리하기
비동기 메소드 호출 후 각 메소드의 결과마다 await을 설정해 대기하지 않고,
미리 LIST로 담은 후 Task.Whenall(list)로 처리 할 수 있습니다.
아래 코드를 확인해보면 Task.WhenAll 라인에서 모든 요청이 종료될때까지 대기되며, 완료된 이후에
다음라인이 실행됩니다. 모든 비동기 요청의 결과 값은 HttpResponseMessage[] 배열에 저장 되어
필요한 경우 꺼내 쓰면 됩니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTest
{
class Program
{
static async Task Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Console.WriteLine("비동기 3회 시작");
Task<HttpResponseMessage> first = PostAsyncHttp();
Task<HttpResponseMessage> second = PostAsyncHttp();
Task<HttpResponseMessage> third = PostAsyncHttp();
Task<HttpResponseMessage> test1 = PostAsyncHttp();
Task<HttpResponseMessage> test2 = PostAsyncHttp();
Task<HttpResponseMessage> test3 = PostAsyncHttp();
Task<HttpResponseMessage> test4 = PostAsyncHttp();
Task<HttpResponseMessage> test5 = PostAsyncHttp();
Task<HttpResponseMessage> test6 = PostAsyncHttp();
Task<HttpResponseMessage> test7 = PostAsyncHttp();
List<Task<HttpResponseMessage>> list = new List<Task<HttpResponseMessage>>();
list.Add(first);
list.Add(second);
list.Add(test1);
list.Add(test2);
list.Add(test3);
list.Add(test4);
list.Add(test5);
list.Add(test6);
list.Add(test7);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("다른 로직 수행 : " + i);
}
HttpResponseMessage[] response = await Task.WhenAll(list);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds+"ms");
Thread.Sleep(5000);
}
public static async Task<HttpResponseMessage> PostAsyncHttp()
{
HttpClient _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer Ask2O1C1EUq0iNdBGAVGx4Jm9mUvcSLmfvgV61OH1nY");
var parameters = new Dictionary<string, string>();
parameters.Add("message", "안녕하세요");
var encodedContent = new FormUrlEncodedContent(parameters);
var response = await _httpClient.PostAsync("https://notify-api.line.me/api/notify", encodedContent).ConfigureAwait(false);
Console.WriteLine("비동기 PostAsyncHttp() 호출");
return response;
}
}
}
'C# > 기본' 카테고리의 다른 글
[C#] C# 에서 Mysql연동하기 (insert, select) (3) | 2019.11.03 |
---|---|
[C#] async, await 비동기 프로그램 작성하기 (0) | 2019.11.02 |
[C#] visual studio 2019 파일 더블 클릭으로 열게 하기 (0) | 2019.11.01 |
[C#] 문자열 byte로 변환하기 (1) | 2019.10.25 |
[C#] 문자열 자르기 붙이기 split join substring (0) | 2019.10.25 |
최근댓글