|
|||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||
|
Припинення
і знищення потоків
Простір імен
Threading містить і інші методи, що
переривають нормальне
функціонування потоків:
Важко сказати,
навіщо в .NET була включена підтримка
цих методів — при виклику Suspend і Abort
програма, швидше за все,
почне працювати нестабільно. Жоден з
методів не дозволяє нормально
провести дєїніциалізацию потоку.
Крім того, при виклику Suspend або Abort
неможливо передбачити, в якому
стані потік залишить об'єкти
після припинення або аварійного
завершення. В результаті
виклику Abort ініціюється виключення
Threadabortexception. Щоб ви зрозуміли, чому
це дивне виключення не слід
обробляти в програмах, ми
наводимо уривок з документації .NET
SDK: «...При
знищенні потоку викликом Abort
виконавче середовище ініціює
виключення Threadabortexception. Це особливий
різновид виключень, який
не може перехоплюватися
програмою. При ініціації
цього виключення перед тим, як
знищити потік, виконавче
середовище виконує всі блоки Finally.
Оскільки в блоках Finally можуть
виконуватися будь-які дії,
викличте Join, щоб переконатися в
знищенні потоку». Мораль: Abort і Suspend використовувати
не рекомендується (а якщо
без Suspend все ж таки не обійтися, відновите
припинений потік
методом Resume). Безпечно завершити
потік можна тільки шляхом опиту
умовної змінної, що
синхронізується, або викликом методу
Interrupt, про який мовилося вище.
Деякі
потоки, що працюють у фоновому
режимі, автоматично припиняють роботу
в той момент, коли
зупиняються інші компоненти програми.
Зокрема, складальник сміття працює
в одному з фонових потоків. Зазвичай
фонові потоки створюються для
прийому даних, але це робиться лише
в тому випадку, якщо в інших потоках
працює код, здатний обробити
отримані дані. Синтаксис: ім'я
потоку.IsBackGround = True
Серйозніший
приклад: витягання даних з коди
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
|
|
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||