我正在建立一个与API交互的类库。我需要调用API并处理XML响应。我可以看到使用HttpClient
进行异步连接的好处,但是我正在做的事情纯粹是同步的,所以我看不出使用会有什么明显的好处HttpWebRequest
。
如果有人能阐明任何想法,我将不胜感激。为此我不是使用新技术的人。
我正在建立一个与API交互的类库。我需要调用API并处理XML响应。我可以看到使用HttpClient
进行异步连接的好处,但是我正在做的事情纯粹是同步的,所以我看不出使用会有什么明显的好处HttpWebRequest
。
如果有人能阐明任何想法,我将不胜感激。为此我不是使用新技术的人。
Answers:
但是我在做的事情完全是同步的
您可以使用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
over WebRequest
而言,HttpClient
新孩子正在开发中,并且可能包含对旧客户的改进。
string responseString = Task.Run(() => responseContent.ReadAsStringAsync()).Result;
如果您必须使同步,则可能需要考虑类似的方法。
Task.Run
从ThreadPool调用任务,但是您正在调用.Result
它杀死所有由此带来的好处,并阻塞了您在其中调用此线程的线程.Result
(通常恰好是主UI线程)。
.Result
可能会耗尽线程池并导致死锁。
new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()
我再次重申Donny V. Answer和Josh's
“我不使用异步版本的唯一原因是,如果我试图支持尚未内置异步支持的.NET较旧版本。”
(如果我有声誉,请投票。)
我不记得上一次(如果有的话),我很感谢HttpWebRequest抛出了状态代码> = 400的异常。要解决这些问题,您需要立即捕获异常,并将它们映射到某些非异常响应机制在您的代码中...本身无聊,乏味且容易出错。无论是与数据库通信还是实现定制的Web代理,“近乎”总是希望Http驱动程序仅告诉您的应用程序代码返回了什么,并由您决定如何执行。
因此,最好使用HttpClient。
HttpClient
本身是一个包装器HttpWebRequest
(实际上,在内部捕获了这些WebException
对象并HttpResponseMessage
为您转换为a )。我本以为完全从头开始构建新客户端会更容易。
就我而言,接受的答案无效。我从没有异步动作的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());
如果使用该类将async方法作为参数传递,则可以安全的方式从sync方法中调用async方法。
在这里解释:https : //cpratt.co/async-tips-tricks/
所有答案似乎都集中在HttpClient
同步使用上,而不是给出问题的实际答案。
HttpClient
它不仅仅是一个简单的请求/响应处理程序,因此它可以处理不同网络的某些特殊情况。也就是说,在我的情况下,使用需要协商的NTLM代理,在客户端和代理服务器之间发送带有令牌和凭据的多个请求/响应以进行身份验证。HttpClient
(使用HttpClientHandler
)似乎具有内置的机制,该机制可以通过一种方法调用来返回超出代理的资源。