我正在构建一个与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);
    }
}

至于为什么你应该在WebRequest上使用HttpClient,好吧,HttpClient是块上的新孩子,可以包含对旧客户端的改进。

其他回答

在当今时代,对这个问题的最简短的回答是非常直接的:字面上说,除了HttpClient之外的所有先前的。net选项现在都已弃用/过时了。

如果您正在构建一个类库,那么您的库的用户可能希望异步使用您的库。我认为这是最大的原因。

您也不知道您的库将如何使用。也许用户将处理大量的请求,异步处理将帮助它更快更有效地执行。

如果您可以简单地做到这一点,那么当您可以为库的用户处理流时,尽量不要让他们承担试图使流异步化的负担。

我不使用异步版本的唯一原因是,如果我试图支持一个尚未内置异步支持的旧版本的。net。

但是我所做的是完全同步的

你可以使用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);
    }
}

至于为什么你应该在WebRequest上使用HttpClient,好吧,HttpClient是块上的新孩子,可以包含对旧客户端的改进。

在我的情况下,公认的答案不起作用。我从一个没有异步动作的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();
}

Then

AsyncHelper.RunSync(() => DoAsyncStuff());

如果你使用这个类来传递你的async方法作为参数,你可以以一种安全的方式从sync方法调用async方法。

解释如下: https://cpratt.co/async-tips-tricks/