Я использую сервис проверки W3C, чтобы проверить, что текст, который я ввожу в TextBox, является допустимой разметкой.
Это почти работает. Но при определенных условиях мой ввод приводит к ошибке, а затем к бесконечным исключениям тайм-аута. Я должен закрыть заново открыть программу, чтобы она снова заработала.
Пожалуйста, просмотрите мой код и помогите мне решить эту проблему.
У меня довольно простое приложение WPF с TextBox и StatusBar. StatusBar обновляется по мере ввода, чтобы сообщить мне, является ли моя напечатанная разметка действительной или нет. Чтобы служба не работала, проверки выполняются только через одну секунду или более без нажатия клавиш.
Неверно http://img9.imageshack.us/img9/3788/invalidr.gif
В нем StatusBar может отображать: «Validating ...», «Valid», «Invalid» или - если оно было - сообщение об исключении.
Проверка http://img7.imageshack.us/img7/5842/validating.gif
Следующее успешно подтверждено:
XHTML Input
<?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>
Если я нарушу свой абзац как <p>This is a test</
, то получу это исключение при попытке обработать ответ XML:
Имя не может начинаться с «»
символ, шестнадцатеричное значение 0x22.
Линия 86, позиция 40.
Исключение XML http://img11.imageshack.us/img11/3066/namecannotbegin.gif
Если проверка два раза подряд не проходит, то кажется, что я не могу просто исправить свои теги абзаца и продолжить как обычно. По какой-то причине каждая последующая проверка завершается неудачей с этим исключением:
Время ожидания истекло
Тайм-аут http://img21.imageshack.us/img21/7600/timedout.gif
Это очень странно.
Извините, что опубликовал весь мой проект, но я не знаю, откуда возникла моя проблема. Это может быть мои потоки, связь с веб-сервисом, обработка исключений ... Я просто не могу найти это. Правильно ли я закрываю свои StreamWriter, HttpWebRequest и ResponseStreams?
* * Тысяча сорок-девять * 1050 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
Спасибо за любую помощь!