【问题标题】:WCF service call async functionWCF 服务调用异步函数
【发布时间】:2018-09-07 22:17:22
【问题描述】:

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

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", "***" }
        };
    }
}

这个函数在 console 项目中运行良好,但是当我尝试将此函数移动到 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."}

【问题讨论】:

  • 顺便提一下,过早调用Result 会破坏async 的全部目的
  • 还有死锁..
  • @MickyD,谢谢您的回复。该函数只是一个隐藏一些细节的演示函数。我的核心问题是该功能在 WCF 中不起作用。你能帮忙吗?
  • @PauloMorgado,感谢您的回复。对我的问题有什么建议吗?
  • 我们如何知道哪些代码是真实的?发布您的实际代码。祝你好运!

标签: c# wcf asynchronous async-await httprequest


【解决方案1】:

使用 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;

【讨论】:

  • 感谢您的回复。我按照您的建议修改了我的代码,但在 WCF 服务中仍然失败。抛出了同样的异常。如果您能提供进一步的建议,我们将不胜感激。再次感谢!
  • @Kerwen chekc 在您调用 HTTPS、URL 时查看是否是证书问题
  • 是的!添加 SecurityProtocol 后,它就可以工作了!感谢您的努力,恩科西!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 2012-10-03
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多