代码之家  ›  专栏  ›  技术社区  ›  Kerwen

WCF服务调用异步函数

  •  0
  • Kerwen  · 技术社区  · 6 年前

    我有一个异步函数,用于向服务器发送请求消息。功能如下:

    class http
    {
        public async Task<string> HttpRequest()
        {
            HttpRequestMessage request = GetHttpRequestMessage();
            var str1 = await ExecuteRequest(request);
            return str1;
        }
    
        private async Task<string> ExecuteRequest(HttpRequestMessage request)
        {
            string result = string.Empty;
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    var responses = await client.SendAsync(request);
                    responses.EnsureSuccessStatusCode();
                    result = await responses.Content.ReadAsStringAsync();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
    
            return result;
        }
    
        private const string _DataTypeJson = @"application/json";
        private HttpRequestMessage GetHttpRequestMessage()
        {
            Dictionary<string, string> headers = GetHeadersUsedForToken();
            string str = "https://test.com//tokens";
            Uri uri = new Uri(str);
    
            HttpRequestMessage request = new HttpRequestMessage
            {
                RequestUri = uri,
            };
    
            if (null != headers)
            {
                foreach (string key in headers.Keys)
                {
                    request.Headers.Add(key, headers[key]);
                }
            }
    
            // Hard code Accpt type is Json
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(_DataTypeJson));
    
            request.Method = HttpMethod.Get;
            return request;
        }
    
        private Dictionary<string, string> GetHeadersUsedForToken()
        {
            return new Dictionary<string, string>
            {
                { "id", "abc" },
                { "secret", "***" }
            };
        }
    }
    

    此功能在 安慰 但当我尝试将此函数移动到WCF服务,并尝试调用 HttpRequest() 使用中的功能,

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        Task<string> GetData();
    }
    public class Service1 : IService1
    {
        public Task<string> GetData()
        {
            http test = new http();
            return test.HttpRequest();
        }       
    }
    

    引发异常:

    Message An error occurred while sending the request.
    InnerException  {"The underlying connection was closed: An unexpected error occurred on a send."}
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Nkosi    6 年前

    使用async/await,您需要使其始终异步。

    使服务成为基于任务的异步服务

    [ServiceContract]
    public interface IService1 {
        [OperationContract]
        Task<string> GetData();
    }
    

    因此,只需使其余代码始终异步即可。

    public class http {
        public async Task<string> HttpRequestAsync() {
            var request = GetHttpRequestMessage();
            string str1 = await ExecuteRequest(request);
            Console.WriteLine(str1);
            return str1;
        }
    
        //...code removed for brevity as they are already Task-based
    }
    

    这现在应该允许在服务实现中使用该功能

    public class Service1 : IService1 {
        public Task<string> GetData() {
            http test = new http(); 
            return test.HttpRequestAsync();
        }
    }
    

    在提供的原始示例中,代码混合了异步调用和阻塞调用 .Result ,这可能导致死锁

    参考 Async/Await - Best Practices in Asynchronous Programming

    我还建议 HttpClient 静态并重用它,而不是创建多个实例并对其进行处理。

    参考 keep an instance of HttpClient for the lifetime of your application for each distinct API that you connect to.

    更新时间:

    另一种可能是调用的URL是HTTPS。

    在通过 HttpClient

    //Handle TLS protocols
    System.Net.ServicePointManager.SecurityProtocol =
        System.Net.SecurityProtocolType.Tls
        | System.Net.SecurityProtocolType.Tls11
        | System.Net.SecurityProtocolType.Tls12;