API와 상호 작용할 클래스 라이브러리를 작성 중입니다. API를 호출하고 XML 응답을 처리해야합니다. HttpClient
비동기 연결 에 사용하면 얻을 수있는 이점을 볼 수 있지만 내가하는 일은 순전히 동기이므로를 사용하는 것보다 큰 이점을 볼 수 없습니다 HttpWebRequest
.
누구든지 어떤 빛을 발산 할 수 있다면 크게 감사하겠습니다. 나는 그것을 위해 새로운 기술을 사용하는 사람이 아닙니다.
API와 상호 작용할 클래스 라이브러리를 작성 중입니다. API를 호출하고 XML 응답을 처리해야합니다. HttpClient
비동기 연결 에 사용하면 얻을 수있는 이점을 볼 수 있지만 내가하는 일은 순전히 동기이므로를 사용하는 것보다 큰 이점을 볼 수 없습니다 HttpWebRequest
.
누구든지 어떤 빛을 발산 할 수 있다면 크게 감사하겠습니다. 나는 그것을 위해 새로운 기술을 사용하는 사람이 아닙니다.
답변:
하지만 내가하고있는 일은 순전히 동기입니다
HttpClient
동기식 요청에는 잘 사용할 수 있습니다 .
using (var client = new HttpClient())
{
var response = client.GetAsync("http://google.com").Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
// by calling .Result you are synchronously reading the result
string responseString = responseContent.ReadAsStringAsync().Result;
Console.WriteLine(responseString);
}
}
왜 HttpClient
오버 오버 를 사용 해야하는지 WebRequest
에 관한 한, HttpClient
새로운 아이가 블록에 있고 오래된 클라이언트보다 개선 사항이 포함될 수 있습니다.
string responseString = Task.Run(() => responseContent.ReadAsStringAsync()).Result;
대신하는 경우 합니다 이 동기하게합니다.
Task.Run
는 ThreadPool에서 작업을 호출하지만, .Result
이것으로 모든 이점을 없애고 호출 한 스레드 .Result
(일반적으로 기본 UI 스레드)를 차단합니다 .
.Result
같이 호출 하면 스레드 풀이 소모되고 교착 상태가 발생할 수 있습니다.
new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()
Donny V. 답변과 Josh 's를 다시 반복하겠습니다.
"비동기 버전을 사용하지 않는 유일한 이유는 이미 비동기 지원 기능이 내장되어 있지 않은 이전 버전의 .NET을 지원하려고했기 때문입니다."
(그리고 평판이 있다면 공감하십시오.)
HttpWebRequest가 상태 코드> = 400에 대해 예외를 발생시킨 사실에 대해 마지막으로 기억할 수 없었습니다. 이러한 문제를 해결하려면 예외를 즉시 포착하고 예외가 아닌 응답 메커니즘에 매핑해야합니다. 코드에서 ... 지루하고 지루하며 오류가 발생하기 쉽습니다. 데이터베이스와 통신하든, 맞춤형 웹 프록시를 구현하든, 항상 '거의'HTTP 드라이버는 애플리케이션 코드에 리턴 된 내용을 알려주고 동작 방식을 결정하도록하는 것이 바람직합니다.
따라서 HttpClient가 바람직합니다.
HttpClient
자체가 래퍼 주위가 HttpWebRequest
(실제로, 내부적으로 그 연결되는지 WebException
오브젝트를하고로의 전환을하지 HttpResponseMessage
당신을 위해). 처음부터 완전히 새로운 클라이언트를 만드는 것이 더 쉬울 것이라고 생각했을 것입니다.
클래스 라이브러리를 작성하는 경우 라이브러리 사용자가 라이브러리를 비동기 적으로 사용하려고합니다. 이것이 바로 가장 큰 이유라고 생각합니다.
당신은 또한 당신의 라이브러리가 어떻게 사용 될지 모른다. 아마도 사용자는 많은 요청을 처리하고 비동기 적으로 수행하면 더 빠르고 효율적으로 수행하는 데 도움이 될 것입니다.
간단하게 처리 할 수 있으면 라이브러리 사용자가 처리 할 수있을 때 플로우를 비 동기화하려고하는 라이브러리 사용자에게 부담을주지 마십시오.
비동기 버전을 사용하지 않는 유일한 이유는 이미 비동기 지원 기능이 내장되어 있지 않은 이전 버전의 .NET을 지원하려는 경우입니다.
제 경우에는 받아 들여진 대답이 효과가 없었습니다. 비동기 작업이없는 MVC 응용 프로그램에서 API를 호출했습니다.
이것이 내가 작동하게하는 방법입니다.
private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public static T RunSync<T>(Func<Task<T>> func)
{
CultureInfo cultureUi = CultureInfo.CurrentUICulture;
CultureInfo culture = CultureInfo.CurrentCulture;
return _myTaskFactory.StartNew<Task<T>>(delegate
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = cultureUi;
return func();
}).Unwrap<T>().GetAwaiter().GetResult();
}
그런 다음 나는 이것을 이렇게 불렀다.
Helper.RunSync(new Func<Task<ReturnTypeGoesHere>>(async () => await AsyncCallGoesHere(myparameter)));
public static class AsyncHelper
{
private static readonly TaskFactory _taskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
=> _taskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
public static void RunSync(Func<Task> func)
=> _taskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
그때
AsyncHelper.RunSync(() => DoAsyncStuff());
해당 클래스를 사용하면 비동기 메서드를 매개 변수로 전달하면 안전한 방법으로 동기화 메서드에서 비동기 메서드를 호출 할 수 있습니다.
여기에 설명되어 있습니다 : https://cpratt.co/async-tips-tricks/
모든 답변은 HttpClient
실제 질문에 대한 답변을 제공하는 대신 동기식 으로 사용하는 데 집중하는 것 같습니다 .
HttpClient
는 단순한 요청 / 응답 처리기 이상이므로 다른 네트워크의 특성을 처리 할 수 있습니다. 내 경우에는 협상이 필요한 NTLM 프록시를 사용하여 인증하기 위해 클라이언트와 프록시 서버간에 토큰 및 자격 증명을 사용하여 여러 요청 / 응답을 보냅니다. HttpClient
(사용 HttpClientHandler
)에는 하나의 메서드 호출로 프록시 이외의 리소스를 반환하는 처리 메커니즘이 내장되어있는 것 같습니다.