0

我正在尝试使用 C# 中的 HttpClient 将和 POST 到 URL。出于扩展目的,我需要异步执行此操作。但是,我只能让我的 PUT 和 POST 同步工作。下面是我用来将 JSON 格式的 ZoomData 对象放入 URL 的代码:

// takes the dataset to PUT and PUTs to server
    public async Task<HttpResponseMessage> JsonPUTcall(ZoomData toPut)
    {
        string jsonString = JsonConvert.SerializeObject(toPut);
        return await client.PutAsync(InsiteDatasetPutURL.Replace("sys_id", toPut.sys_id), new StringContent(jsonString, UnicodeEncoding.UTF8, "application/json"));
    }

这是我用来将队列中的 ZoomData 对象实际传递给 JsonPUTcall 的代码:

public async void JsonPUTqueueCall(Queue<ZoomData> toPut)
    {
        if (toPut.Count == 0)
            return;
        foreach (var zoomData in toPut)
        {
            var result = await this.JsonPUTcall(zoomData);                                
        }
    }

但是,当我尝试这样做时,它只是挂起。因此,作为测试,我替换了“var result = await this.JsonPUTcall(zoomData);” 具有以下内容:

public async void JsonPUTqueueCall(Queue<ZoomData> toPut)
    {
        if (toPut.Count == 0)
            return;
        foreach (var zoomData in toPut)
        {
            var result = this.JsonPUTcall(zoomData);
            result.Wait();                                
        }
    }

这行得通,但由于它是同步的,它违背了使用异步的目的。我错过了什么?

4

2 回答 2

3

这是我的 API 客户端,它可以有效地使用资源并且方法是异步的

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
//You need to install package Newtonsoft.Json > https://www.nuget.org/packages/Newtonsoft.Json/
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;


public class MyApiClient : IDisposable
{
    private readonly TimeSpan _timeout;
    private HttpClient _httpClient;
    private HttpClientHandler _httpClientHandler;
    private readonly string _baseUrl;
    private const string ClientUserAgent = "my-api-client-v1";
    private const string MediaTypeJson = "application/json";

    public MyApiClient(string baseUrl, TimeSpan? timeout = null)
    {
        _baseUrl = NormalizeBaseUrl(baseUrl);
        _timeout = timeout ?? TimeSpan.FromSeconds(90);
    }

    public async Task<string> PostAsync(string url, object input)
    {
        EnsureHttpClientCreated();

        using (var requestContent = new StringContent(ConvertToJsonString(input), Encoding.UTF8, MediaTypeJson))
        {
            using (var response = await _httpClient.PostAsync(url, requestContent))
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
        }
    }

    public async Task<TResult> PostAsync<TResult>(string url, object input) where TResult : class, new()
    {
        var strResponse = await PostAsync(url, input);

        return JsonConvert.DeserializeObject<TResult>(strResponse, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
    }

    public async Task<TResult> GetAsync<TResult>(string url) where TResult : class, new()
    {
        var strResponse = await GetAsync(url);

        return JsonConvert.DeserializeObject<TResult>(strResponse, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
    }

    public async Task<string> GetAsync(string url)
    {
        EnsureHttpClientCreated();

        using (var response = await _httpClient.GetAsync(url))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }

    public async Task<string> PutAsync(string url, object input)
    {
        return await PutAsync(url, new StringContent(JsonConvert.SerializeObject(input), Encoding.UTF8, MediaTypeJson));
    }

    public async Task<string> PutAsync(string url, HttpContent content)
    {
        EnsureHttpClientCreated();

        using (var response = await _httpClient.PutAsync(url, content))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }

    public async Task<string> DeleteAsync(string url)
    {
        EnsureHttpClientCreated();

        using (var response = await _httpClient.DeleteAsync(url))
        {
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }

    public void Dispose()
    {
        _httpClientHandler?.Dispose();
        _httpClient?.Dispose();
    }

    private void CreateHttpClient()
    {
        _httpClientHandler = new HttpClientHandler
        {
            AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
        };

        _httpClient = new HttpClient(_httpClientHandler, false)
        {
            Timeout = _timeout
        };

        _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(ClientUserAgent);

        if (!string.IsNullOrWhiteSpace(_baseUrl))
        {
            _httpClient.BaseAddress = new Uri(_baseUrl);
        }

        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeJson));
    }

    private void EnsureHttpClientCreated()
    {
        if (_httpClient == null)
        {
            CreateHttpClient();
        }
    }

    private static string ConvertToJsonString(object obj)
    {
        if (obj == null)
        {
            return string.Empty;
        }

        return JsonConvert.SerializeObject(obj, new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });
    }

    private static string NormalizeBaseUrl(string url)
    {
        return url.EndsWith("/") ? url : url + "/";
    }
}

用法

using ( var client = new MyApiClient("http://localhost:8080"))
{
    var response = client.GetAsync("api/users/findByUsername?username=alper").Result;
    var userResponse = client.GetAsync<MyUser>("api/users/findByUsername?username=alper").Result;
}
于 2018-09-04T06:41:47.363 回答
0

这两行是为了使它同步:

var result = this.JsonPUTcall(zoomData);
 result.Wait();      

要使其异步,您讨厌这样做:

var result = await this.JsonPUTcall(zoomData);
于 2018-10-20T19:04:37.027 回答