WCF服务异步调用及HTTP请求异步函数实现技术咨询
嘿,针对你提到的WCF服务异步调用需求,还有你写的这个HTTP异步请求函数,我来给你梳理下关键点和优化建议,帮你把这块实现得更稳健~
首先先把你提供的代码补全并整理好,方便咱们分析:
class HttpService { public async Task<string> SendWcfRequestAsync() { HttpRequestMessage request = BuildWcfRequestMessage(); var responseContent = await ExecuteHttpRequestAsync(request); return responseContent; } private async Task<string> ExecuteHttpRequestAsync(HttpRequestMessage request) { string result = string.Empty; try { using (HttpClient client = new HttpClient()) { var response = await client.SendAsync(request); // 这里要先确保请求成功,再读取内容 response.EnsureSuccessStatusCode(); result = await response.Content.ReadAsStringAsync(); } } catch (HttpRequestException ex) { Console.WriteLine($"调用WCF服务时出错:{ex.Message}"); // 可以根据业务需求选择抛出异常或者返回错误标记 throw; } return result; } // 构造WCF所需的SOAP请求消息 private HttpRequestMessage BuildWcfRequestMessage() { // 示例:替换成你的WCF服务地址和具体SOAP内容 var request = new HttpRequestMessage(HttpMethod.Post, "http://your-wcf-service/Service.svc/YourTargetOperation"); // WCF的SOAP请求通常用text/xml类型 request.Content = new StringContent("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">...</SOAP-ENV:Envelope>", Encoding.UTF8, "text/xml"); return request; } }
接下来聊几个核心的优化点和WCF异步调用的可选方案:
1. 别每次都新建HttpClient!
你现在在ExecuteHttpRequestAsync里每次都创建HttpClient实例,这在高并发场景下很容易导致Socket资源耗尽——因为HttpClient的底层连接池不会被正确复用。最佳实践是把HttpClient做成类的静态成员,全局复用:
class HttpService { // 静态HttpClient实例,整个应用生命周期复用 private static readonly HttpClient _sharedHttpClient = new HttpClient(); public async Task<string> SendWcfRequestAsync() { HttpRequestMessage request = BuildWcfRequestMessage(); var responseContent = await ExecuteHttpRequestAsync(request); return responseContent; } private async Task<string> ExecuteHttpRequestAsync(HttpRequestMessage request) { string result = string.Empty; try { var response = await _sharedHttpClient.SendAsync(request); response.EnsureSuccessStatusCode(); result = await response.Content.ReadAsStringAsync(); } catch (HttpRequestException ex) { Console.WriteLine($"WCF服务请求失败:{ex.Message}"); throw; } return result; } // ...其他方法 }
2. WCF原生异步调用比手动发HTTP更靠谱
你现在用HttpClient手动构造SOAP请求的方式虽然可行,但WCF本身提供了更原生的异步调用方案,能帮你自动处理消息序列化、头部校验、错误封装这些细节,不用自己拼SOAP字符串:
方案A:添加服务引用时生成异步方法
在Visual Studio里添加WCF服务引用时,勾选“生成异步操作”选项,工具会自动生成带Task返回值的异步调用方法,直接用就行:
// 假设添加服务引用后生成的客户端类是YourWcfServiceClient public async Task<string> CallWcfNativeAsync() { using (var client = new YourWcfServiceClient()) { // 直接调用自动生成的异步方法 return await client.YourTargetOperationAsync(); } }
方案B:用ChannelFactory手动创建异步代理
如果不想添加服务引用(比如需要动态切换地址),可以用ChannelFactory创建客户端代理,调用异步合约方法:
// 先定义和WCF服务一致的接口合约 [ServiceContract] public interface IYourWcfContract { [OperationContract(Action = "http://your-service-namespace/YourTargetOperation")] Task<string> YourTargetOperationAsync(); } public async Task<string> CallWcfWithChannelFactoryAsync() { var binding = new BasicHttpBinding(); var endpoint = new EndpointAddress("http://your-wcf-service/Service.svc"); using (var factory = new ChannelFactory<IYourWcfContract>(binding, endpoint)) { IYourWcfContract client = factory.CreateChannel(); var result = await client.YourTargetOperationAsync(); // 关闭客户端通道 ((IClientChannel)client).Close(); return result; } }
3. 异步代码的几个小细节
- 绝对不要在异步方法里用
.Result或者.Wait(),这会导致线程死锁(尤其是在ASP.NET、WPF这类有同步上下文的环境里)。 - 异常处理要覆盖全面:除了
HttpRequestException,如果用WCF原生调用,还要处理CommunicationException、FaultException这些WCF特有的异常。 - 如果你的
BuildWcfRequestMessage里有复杂的SOAP构造,建议用XmlSerializer或者DataContractSerializer来序列化对象,别手动拼XML字符串,容易出错。
内容的提问来源于stack exchange,提问作者Kerwen
相关产品推荐
相关产品推荐

