如何解决调用 HttpListener.GetContextAsync() 后如何正确取消请求?
我正在努力以不产生 IO 异常的方式关闭 HttpListener。
看来我要么以不寻常的方式使用 HttpListener,要么遗漏了一些明显的东西。
我正在设置一个 HttpListener 来监听来自 OAuth2.0 登录的重定向。 我正在尝试启动侦听器,然后打开 Web 浏览器控件进行登录,然后在执行重定向后关闭侦听器。
如果我关闭登录窗口以中止登录,然后重试但再次中止,我会收到此错误:
The I/O operation has been aborted because of either a thread exit or an application request
这是堆栈跟踪:
System.Net.HttpListener.EndGetContext(IAsyncResult asyncResult)
System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar,Func`2 endFunction,Action`1 endAction,Task`1 promise,Boolean requiresSynchronization)
--- End of stack trace from prevIoUs location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
BridgeIT.cOAuth2.VB$StateMachine_49_ListenForAuth.MoveNext() in xxx\cOAuth2.vb:line 235
我曾尝试改用 Begin/EndGetContext() 方法,但它们只是产生相同的结果。
我错过了什么?
Public Function Login(ByVal vsLoginUrl As String,ByVal vsClientID As String,ByVal voScopes As IEnumerable(Of String)) As Boolean
Dim bSuccess As Boolean = False
Dim oAR As AuthenticationResult = nothing
Dim frm As frmOAuth2LoginDlg
Dim sResponseType As String = "code"
Dim sScope As String = String.Join(" ",voScopes)
Dim sstate As String = gsPracticeID
Dim sCodeChallenge As String = GenerateCodeChallenge()
Dim sCodeChallengeMethod As String = "S256"
'Append query string params
vsLoginUrl = $"{vsLoginUrl}?response_type={sResponseType}&client_id={vsClientID}&redirect_uri={msRedirectURL}&scope={sScope}&state={sstate}&code_challenge={sCodeChallenge}&code_challenge_method={sCodeChallengeMethod}"
Try
'Listen for the the oAuth redirect
ListenForAuth()
'Open web browser control
frm = New frmOAuth2LoginDlg(vsLoginUrl)
frm.ShowDialog()
'Do something after logging in
Catch ex As Exception
ShowError(Err.Number,Err.Description,ex)
Finally
CloseRedirectListener()
dispoSEOfObject(frm)
End Try
End Function
和监听函数:
Private Async Sub ListenForAuth()
Dim oContext As HttpListenerContext
Dim oRequest As HttpListenerRequest
Dim oResponse As HttpListenerResponse
moRedirectListener = New HttpListener
moRedirectListener.Prefixes.Add(msRedirectURL)
moRedirectListener.Start()
Try
oContext = Await moRedirectListener.GetContextAsync()
oRequest = oContext.Request
'Do something with the request
Catch oex As ObjectdisposedException
' Safely ignore this if the listener has been closed
' Else rethrow the exception
If oex.ObjectName <> "System.Net.HttpListener" Then
Throw
End If
Catch ex As Exception
ShowError(Err.Number,ex)
End Try
End Sub
和 CloseRedirectListener 函数:
Private Sub CloseRedirectListener()
If moRedirectListener IsNot nothing Then
moRedirectListener.Stop()
moRedirectListener.Prefixes.Remove(msRedirectURL)
moRedirectListener.Close()
End If
End Sub
解决方法
这个问题似乎没有太大变化,所以我会为其他人发布我的解决方案,直到提供更好的解决方案。
捕获特定异常是我发现异步处理取消请求的唯一方法:
Private Async Function ListenForAuth(frm As frmOAuth2LoginDlg) As Task
Dim oContext As HttpListenerContext
Dim oRequest As HttpListenerRequest
moRedirectListener = New HttpListener
moRedirectListener.Prefixes.Add(RedirectURL)
moRedirectListener.Start()
Try
oContext = Await moRedirectListener.GetContextAsync()
oRequest = oContext.Request
' Do something with the request
' Handle the exceptions in the case of cancelled requests
Catch oObjectDisposedException As ObjectDisposedException
' If the Listener has been closed then safely ignore this
' Else rethrow
If oObjectDisposedException.ObjectName <> "System.Net.HttpListener" Then
Throw
End If
Catch oHttpListenerException As System.Net.HttpListenerException
' If the Listener has been stopped then safely ignore this
' Else rethrow
If oHttpListenerException.Message <> "The I/O operation has been aborted because Of either a thread Exit Or an application request" Then
Throw
End If
Catch ex As Exception
' Do something with other exceptions
Finally
If Application.OpenForms.OfType(Of frmOAuth2LoginDlg).Count > 0 Then
frm.Close()
End If
End Try
End Function
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。