我正在构建一个类库来与 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
over WebRequest
,嗯,HttpClient
是新的孩子,可能包含对旧客户端的改进。
我会重申 Donny V. answer 和 Josh 的
“我不使用异步版本的唯一原因是,如果我试图支持尚未内置异步支持的旧版本 .NET。”
(如果我有声誉,请投票。)
我不记得上次是什么时候了,我很感激 HttpWebRequest 抛出状态码 >= 400 的异常。要解决这些问题,您需要立即捕获异常,并将它们映射到一些非异常响应机制在您的代码中......本身很无聊,乏味且容易出错。无论是与数据库通信,还是实现定制的 Web 代理,“几乎”总是希望 Http 驱动程序只告诉您的应用程序代码返回什么,并由您决定如何表现。
因此 HttpClient 更可取。
对于现在遇到此问题的任何人,.NET 5.0 已将同步Send
方法添加到HttpClient
. https://github.com/dotnet/runtime/pull/34948
优点以及为什么在这里详细讨论 - https://github.com/dotnet/runtime/issues/32125
因此,您可以使用 this 而不是SendAsync
. 例如
public string GetValue()
{
var client = new HttpClient();
var webRequest = new HttpRequestMessage(HttpMethod.Post, "http://your-api.com")
{
Content = new StringContent("{ 'some': 'value' }", Encoding.UTF8, "application/json")
};
var response = client.Send(webRequest);
using var reader = new StreamReader(response.Content.ReadAsStream());
return reader.ReadToEnd();
}
这段代码只是一个简化的例子,它还没有准备好生产。
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());
如果您使用该类将您的异步方法作为参数传递,您可以以安全的方式从同步方法中调用异步方法。
如果您正在构建一个类库,那么您的库的用户可能希望异步使用您的库。我认为这是最大的原因。
你也不知道你的图书馆将如何被使用。也许用户会处理大量的请求,而异步执行将有助于它更快、更高效地执行。
如果您可以简单地做到这一点,请尽量不要将负担放在尝试使流程异步的库用户身上,因为您可以为他们处理它。
我不使用异步版本的唯一原因是,如果我试图支持尚未内置异步支持的旧版本 .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)));