简体   繁体   English

请帮我解决我的 W3C 验证 API 超时问题

[英]Please help me solve my W3C validation API timeout issue

I'm using the W3C validation service to check that the text I type into a TextBox is valid markup.我正在使用 W3C 验证服务来检查我在 TextBox 中键入的文本是否是有效的标记。

有效的

It's almost working.它几乎可以工作了。 But, under particular conditions my input results in an error and then endless timeout exceptions.但是,在特定条件下,我的输入会导致错误,然后是无休止的超时异常。 I have to close an re-open the program to get it working again.我必须关闭重新打开程序才能让它再次工作。

Please glance over my code and help me to solve this issue.请浏览我的代码并帮助我解决这个问题。

I've got a pretty simple WPF application with a TextBox and a StatusBar.我有一个非常简单的 WPF 应用程序,带有一个 TextBox 和一个 StatusBar。 The StatusBar updates as I type to let me know if my typed markup is or is not valid.当我输入时,状态栏会更新,让我知道我输入的标记是否有效。 So that I'm not hammering the service, validations occur only after one second or longer has elapsed with no keystrokes.因此,我不会敲击服务,仅在没有击键的情况下经过一秒钟或更长时间后才会进行验证。

Invalid http://img9.imageshack.us/img9/3788/invalidr.gif无效 http://img9.imageshack.us/img9/3788/invalidr.gif

It StatusBar may show: "Validating...", "Valid", "Invalid", or--if there's been one--an exception's message.它的状态栏可能会显示:“正在验证...”、“有效”、“无效”,或者——如果有的话——异常的消息。

Validating http://img7.imageshack.us/img7/5842/validating.gif验证 http://img7.imageshack.us/img7/5842/validating.gif

The following validates successfully:以下验证成功:

XHTML Input XHTML 输入

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en">
    <head>
        <title>Test</title>
    </head>
    <body>
        <h1>Test</h1>
        <p>This is a test</p>
    </body>
</html>

If I break my paragraph like <p>This is a test</ then I get this exception while trying to process the response XML:如果我像<p>This is a test</打破我的段落,那么在尝试处理响应 XML 时会出现此异常:

Name cannot begin with the '"' character, hexadecimal value 0x22. Line 86, position 40.名称不能以 '"' 字符开头,十六进制值 0x22。第 86 行,position 40。

XML Exception http://img11.imageshack.us/img11/3066/namecannotbegin.gif XML 异常 http://img11.imageshack.us/img11/3066/namecannotbegin.gif

If validation fails like that twice in a row, then it seems I can't just fix my paragraph tags and continue on like normal.如果验证连续两次失败,那么我似乎不能只修复我的段落标签并像往常一样继续。 For some reason each subsequent validation fails with this exception:由于某种原因,每个后续验证都会失败,并出现以下异常:

The operation has timed out操作已超时

Timed Out http://img21.imageshack.us/img21/7600/timedout.gif超时 http://img21.imageshack.us/img21/7600/timedout.gif

This is very strange.这很奇怪。

I'm sorry to post my whole project, but I don't know where my problem is coming from.很抱歉发布我的整个项目,但我不知道我的问题来自哪里。 It might be my threading, web service communication, exception handling... I just can't seem to find it.可能是我的线程,web 服务通信,异常处理......我似乎找不到它。 Am I closing my StreamWriter, HttpWebRequest, and ResponseStreams correctly?我是否正确关闭了我的 StreamWriter、HttpWebRequest 和 ResponseStreams?

XAML XAML

<Window x:Class="Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="W3C Validation"
        Height="300"
        Width="300"
        Name="Window1">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0"
                 TextWrapping="Wrap"
                 AcceptsReturn="True"
                 VerticalScrollBarVisibility="Visible"
                 FontFamily="Consolas"
                 TextChanged="TextBox_TextChanged" />
        <StatusBar Grid.Row="1">
            <StatusBarItem>
                <TextBlock x:Name="TextBlockResult" />
            </StatusBarItem>
        </StatusBar>
    </Grid>
</Window>

Visual Basic视觉基础

Imports System.ComponentModel
Imports <xmlns:env="http://www.w3.org/2003/05/soap-envelope">
Imports <xmlns:m="http://www.w3.org/2005/10/markup-validator">

Class Window1

    Private WithEvents Worker As BackgroundWorker
    Private _WorkerArgument As String

    Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        InitializeWorker()
    End Sub

    Private Sub InitializeWorker()
        Worker = New BackgroundWorker
        Worker.WorkerSupportsCancellation = True
        AddHandler Worker.DoWork, AddressOf Worker_DoWork
        AddHandler Worker.RunWorkerCompleted, AddressOf Worker_RunWorkerCompleted
    End Sub

    Private Sub TextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.TextChangedEventArgs)
        TryToWork(DirectCast(sender, TextBox).Text)
    End Sub

    Sub TryToWork(ByVal Argument As String)

        If _WorkerArgument IsNot Nothing Then
            _WorkerArgument = Argument
            Exit Sub
        End If

        If Not Worker.IsBusy Then
            TextBlockResult.Text = "Validating..."
            Worker.RunWorkerAsync(Argument)
            Exit Sub
        End If

        _WorkerArgument = Argument
        Worker.CancelAsync()
        Dim RetryTimer As New Windows.Threading.DispatcherTimer
        AddHandler RetryTimer.Tick, AddressOf RetryTicker
        RetryTimer.Interval = New TimeSpan(1) '1 tick'
        RetryTimer.Start()

    End Sub

    Sub RetryTicker(ByVal sender As Object, ByVal e As System.EventArgs)
        If Not Worker.IsBusy Then
            DirectCast(sender, Windows.Threading.DispatcherTimer).Stop()
            TextBlockResult.Text = "Validating..."
            Worker.RunWorkerAsync(_WorkerArgument)
            _WorkerArgument = Nothing
        End If
    End Sub

    Private Sub Worker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        'wait for one second'
        Dim StartTime As DateTime = DateTime.Now()
        While Now.Subtract(StartTime) < New TimeSpan(0, 0, 1)
            If DirectCast(sender, BackgroundWorker).CancellationPending Then
                e.Cancel = True
                Exit Sub
            End If
            System.Threading.Thread.Sleep(New TimeSpan(0, 0, 0, 0, 100)) 'tenth of a second'
        End While
        'then validate'
        e.Result = Validate(DirectCast(e.Argument, String))
    End Sub

    Private Function Validate(ByVal Text As String) As String
        Try
            Dim Url As String = "http://validator.w3.org/check"
            Dim Post As String = "&fragment=" + Web.HttpUtility.UrlEncode(Text) + "&output=soap12"
            Dim ResponseDocument As XDocument = XDocument.Load(New Xml.XmlTextReader(Communicate(Url, Post)))
            If ResponseDocument.Root.<env:Body>.<m:markupvalidationresponse>.<m:validity>.Value = "true" Then
                Return "Valid"
            Else
                Return "Invalid"
            End If
        Catch ex As Exception
            Return ex.Message
        End Try
    End Function

    Private Function Communicate(ByVal Url As String, ByVal Post As String) As System.IO.Stream
        Dim Writer As System.IO.StreamWriter = Nothing
        Dim Request As System.Net.HttpWebRequest = System.Net.WebRequest.Create(Url)
        Request.Method = "POST"
        Request.ContentLength = Post.Length
        Request.ContentType = "application/x-www-form-urlencoded"
        Request.Timeout = 2000 '2 seconds'
        Try
            Writer = New System.IO.StreamWriter(Request.GetRequestStream())
            Writer.Write(Post)
        Catch
        Finally
            If Not Writer Is Nothing Then
                Writer.Close()
            End If
        End Try
        Return Request.GetResponse.GetResponseStream()
    End Function

    Private Sub Worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        If Not e.Cancelled Then
            TextBlockResult.Text = DirectCast(e.Result, String)
        End If
    End Sub

End Class

Thanks for any help!谢谢你的帮助!

On a first glance, I would recomend not trying to validate every time the text is changed.乍一看,我建议不要在每次更改文本时都尝试验证。 That can, and does, get a bit overwhelming.这可以而且确实会让人有点不知所措。 I fear that is what is going on here.我担心这就是这里发生的事情。 Good job on making it Async as that will keep it from blocking but I also suspect it is hiding your issue.让它异步的工作做得很好,因为这样可以防止它阻塞,但我也怀疑它隐藏了你的问题。

Try having the TextChanged event set a flag to execute the validator and then just have the DoWork method run in a tight(ish) loop checking that flag.尝试让 TextChanged 事件设置一个标志来执行验证器,然后让 DoWork 方法在紧密(ish)循环中运行检查该标志。 That will allow it time to complete and not get confused.这将使它有时间完成并且不会感到困惑。 It might take a second or two to get the correct data but shouldn't lock up.可能需要一两秒钟才能获得正确的数据,但不应锁定。

Good luck.祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM