Иллюстрированный самоучитель по VB.NET

Более серьезный пример: извлечение данных из кода HTML


Мы рекомендуем использовать потоки лишь в том случае, когда функциональность программы четко делится на несколько операций. Хорошим примером является программа извлечения данных из кода HTML из главы 9. Наш класс выполняет две операции: выборку данных с сайта Amazon и их обработку. Перед нами идеальный пример ситуации, в которой многопоточное программирование действительно уместно. Мы создаем классы для нескольких разных книг и затем анализируем данные в разных потоках. Создание нового потока для каждой книги повышает эффективность программы, поскольку во время приема данных одним потоком (что может потребовать ожидания на сервере Amazon) другой поток будет занят обработкой уже полученных данных.

Многопоточный вариант этой программы работает эффективнее однопоточного варианта лишь на компьютере с несколькими процессорами или в том случае, если прием дополнительных данных удается эффективно совместить с их анализом.

Как говорилось выше, в потоках могут запускаться только процедуры, не имеющие параметров, поэтому в программу придется внести небольшие изменения. Ниже приведена основная процедура, переписанная с исключением параметров:

Public Sub FindRank()

m_Rank = ScrapeAmazon()

Console.WriteLine("the rank of " & m_Name & "Is " & GetRank)

End Sub

Поскольку нам не удастся воспользоваться комбинированным полем для хранения и выборки информации (написание многопоточных программ с графическим интерфейсом рассматривается в последнем разделе настоящей главы), программа сохраняет данные четырех книг в массиве, определение которого начинается так:

Dim theBook(3.1) As String theBook(0.0) = "1893115992"

theBook(0.l) = "Programming VB .NET" ' И т.д.

Четыре потока создаются в том же цикле, в котором создаются объекты AmazonRanker:

For i= 0 То 3

Try



theRanker = New AmazonRanker(theBook(i.0). theBookd.1))

aThreadStart = New ThreadStar(AddressOf theRanker.FindRan()

aThread = New Thread(aThreadStart)

aThread.Name = theBook(i.l)



aThread.Start() Catch e As Exception

Console.WriteLine(e.Message)

End Try

Next

Ниже приведен полный текст программы:

Option Strict On Imports System.IO Imports System.Net

Imports System.Threading

Module Modulel

Sub Main()

Dim theBook(3.1) As String

theBook(0.0) = "1893115992"

theBook(0.l) = "Programming VB .NET"

theBook(l.0) = "1893115291"

theBook(l.l) = "Database Programming VB .NET"

theBook(2,0) = "1893115623"

theBook(2.1) = "Programmer 's Introduction to C#."

theBook(3.0) = "1893115593"

theBook(3.1) = "Gland the .Net Platform "

Dim i As Integer

Dim theRanker As =AmazonRanker

Dim aThreadStart As Threading.ThreadStart

Dim aThread As Threading.Thread

For i = 0 To 3

Try

theRanker = New AmazonRankerttheBook(i.0). theBook(i.1))

aThreadStart = New ThreadStart(AddressOf theRanker. FindRank)

aThread = New Thread(aThreadStart)

aThread.Name= theBook(i.l)

aThread.Start()

Catch e As Exception

Console.WriteLlnete.Message)

End Try Next

Console.ReadLine()

End Sub

End Module

Public Class AmazonRanker

Private m_URL As String

Private m_Rank As Integer

Private m_Name As String

Public Sub New( ByVal ISBN As String. ByVal theName As String)

m_URL = "http://www.amazon.com/exec/obidos/ASIN/" & ISBN

m_Name = theName End Sub

Public Sub FindRank() m_Rank = ScrapeAmazon()

Console.Writeline("the rank of " & m_Name & "is "

& GetRank) End Sub

Public Readonly Property GetRank() As String Get

If m_Rank <> 0 Then

Return CStr(m_Rank) Else

' Проблемы

End If

End Get

End Property

Public Readonly Property GetName() As String Get

Return m_Name

End Get

End Property

Private Function ScrapeAmazon() As Integer Try

Dim theURL As New Uri(m_URL)

Dim theRequest As WebRequest

theRequest =WebRequest.Create(theURL)

Dim theResponse As WebResponse

theResponse = theRequest.GetResponse

Dim aReader As New StreamReader(theResponse.GetResponseStream())



Dim theData As String

theData = aReader.ReadToEnd

Return Analyze(theData)

Catch E As Exception

Console.WriteLine(E.Message)

Console.WriteLine(E.StackTrace)

Console. ReadLine()

End Try End Function

Private Function Analyze( ByVal theData As String) As Integer

Dim Location As.Integer Location = theData.IndexOf("<b>Amazon.com

Sales Rank:</b>") _

+ "<b>Amazon.com Sales Rank:</b>".Length

Dim temp As String

Do Until theData.Substring(Location.l) = "<" temp = temp

&theData.Substring(Location.l) Location += 1 Loop

Return Clnt(temp)

End Function

End Class

Многопоточные операции часто используются в .NET и пространствах имен ввода-вы-вода, поэтому в библиотеке .NET Framework для них предусмотрены специальные асинхронные методы. Дополнительная информация о применении асинхронных методов при написании многопоточных программ приведена в описании методов BeginGetResponse и EndGetResponse класса HTTPWebRequest


Содержание раздела