.net 请帮助我解决W3C验证API超时问题

.net 请帮助我解决W3C验证API超时问题,.net,web-services,multithreading,backgroundworker,w3c,.net,Web Services,Multithreading,Backgroundworker,W3c,我正在使用W3C验证服务检查我在文本框中键入的文本是否为有效标记 它几乎起作用了。但是,在特定条件下,我的输入会导致一个错误,然后是无休止的超时异常。我必须关闭一个重新打开的程序才能让它重新工作 请浏览我的代码并帮助我解决此问题 我有一个非常简单的WPF应用程序,带有一个文本框和一个状态栏。状态栏在我键入时更新,以让我知道键入的标记是否有效。因此,我不是在敲打服务,验证只在一秒钟或更长时间后发生,没有按键 它的状态栏可能会显示:正在验证…、有效、无效,或者如果存在异常消息 以下内容将成功验证

我正在使用W3C验证服务检查我在文本框中键入的文本是否为有效标记

它几乎起作用了。但是,在特定条件下,我的输入会导致一个错误,然后是无休止的超时异常。我必须关闭一个重新打开的程序才能让它重新工作

请浏览我的代码并帮助我解决此问题

我有一个非常简单的WPF应用程序,带有一个文本框和一个状态栏。状态栏在我键入时更新,以让我知道键入的标记是否有效。因此,我不是在敲打服务,验证只在一秒钟或更长时间后发生,没有按键

它的状态栏可能会显示:正在验证…、有效、无效,或者如果存在异常消息

以下内容将成功验证:

XHTML输入
如果我打破我的段落,就像第一眼看到这是一个测试,我建议不要每次文本更改时都尝试验证。这可能会,而且确实会让人有点不知所措。我担心这就是这里发生的事情。在使其异步方面做得很好,因为这样可以防止阻塞,但我也怀疑它隐藏了您的问题

尝试让TextChanged事件设置一个标志来执行验证器,然后让DoWork方法在一个严格的循环中运行以检查该标志。这将使它有时间完成,而不会感到困惑。可能需要一两秒钟才能获得正确的数据,但不应锁定


祝你好运。

不要担心发布这么多代码。我们喜欢代码。在代码中查找bug比从vauge描述中猜测更容易。您使用的是本地安装的服务副本还是w3.org托管的服务副本?我使用的是w3.org托管的服务。此外,如果您这样做,您可能会被阻止。他们的文档中说,过度使用会被阻止。我已经根据他们的建议在每次验证之间设置了1秒或更长的延迟。
<?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>
<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>
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