Http 请求在从 ServiceBase.OnShutdown 发送时被中止,但在 OnStop 中没有

Posted

技术标签:

【中文标题】Http 请求在从 ServiceBase.OnShutdown 发送时被中止,但在 OnStop 中没有【英文标题】:Http request is aborted when it is being sent from ServiceBase.OnShutdown, but not in OnStop 【发布时间】:2017-10-30 19:34:11 【问题描述】:

我有一个 Windows 服务,它会在 OnShutdownOnStop 中发送一个 https 请求,当我从任务管理器中重新启动该服务时,它工作得很好。但是,当服务因服务器关闭而停止时,相同的代码将引发此异常:

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel. at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()

此外,请求发生在更大的Task 内。

我不确定从任务管理器或服务停止服务与关闭 Windows 会如何使相同的逻辑表现不同。什么可能导致此问题,或者我该如何排除故障?

【问题讨论】:

可能是 Windows 关闭在服务之前关闭了网络。 是的,我其实也是这么想的,但是我该如何确认呢? 尝试枚举所有NetworkInterfaces并检查他们的OperationalStatus 在发送请求之前,用于 Internet 的以太网已启动。环回也是如此。 【参考方案1】:

我无法确定是否在 Task.Run() 中是问题所在,或者还有什么可能导致此请求中止。但是,我可以通过使用 SystemEvents.SessionEnded 事件来防止它被中止:

public void Start()

    SystemEvents.SessionEnded += OnSessionEnded;

...

public void Stop()

    SystemEvents.SessionEnded -= OnSessionEnded;

...

private void OnSessionEnded(object sender, SessionEndedEventArgs eventArgs)

    if (eventArgs.Reason == SessionEndReasons.SystemShutdown)
    
        SendRequest();
    

这是我的代码正在执行的简化版本。当SessionEnded 被触发时发送这个http 请求,而不是等待ServiceBase.OnStop 被调用,允许请求成功完成。并且更改不会影响服务正常关闭的方式。我可以看到的主要区别是它现在发生在服务关闭过程的早期。

【讨论】:

以上是关于Http 请求在从 ServiceBase.OnShutdown 发送时被中止,但在 OnStop 中没有的主要内容,如果未能解决你的问题,请参考以下文章

Web 服务 HTTP 请求未经授权,带有方案摘要

ORA-29273: HTTP 请求失败 ORA-29276: 传输超时

如何在从 jquery 发送 $.get 请求时启用 CORS?

通过 HTTP 请求使用 C# 读取 Json

允许在从 UI 端进行 Post 请求时在 url 中发送特殊字符

Flutter:在 http.get 请求之后构建 ListView