调用 HttpListener.GetContextAsync() 后如何正确取消请求?

如何解决调用 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?