В этом руководстве мы попытаемся пролить свет на тему многопоточности с использованием ASP.NET. Потоки — это метод, используемый для создания у пользователя впечатления, что несколько задач выполняются одновременно. .NET Framework предоставляет нам множество типов, которые позволяют нам легко и быстро добавлять многопоточность в наше веб-приложение .NET. Я предполагаю, что вы немного знакомы с ASP.NET и, по крайней мере, имеете опыт написания кода на Visual Basic.
В этом уроке мы создадим довольно простое веб-приложение, которое должно стать хорошим примером некоторых базовых концепций потоков. В основном у нас будет 2 текстовых поля для ввода фразы и периода времени, в который вы хотите перестроить фразу. Наше веб-приложение для работы с потоками состоит из 2 страниц, одна из которых — страница, с которой начинается поток, а другая — страница с результатами, показывающая ход нашей темы. Предоставленный код должен быть очень переносимым и позволять вам очень быстро реализовать собственное приложение для работы с потоками.
Прежде чем мы начнем …
Прежде чем мы углубимся в веб-приложение, позвольте мне сначала дать вам краткий обзор кода, который вы увидите.
Во-первых, нам нужно импортировать пространство имен System.Threading, чтобы мы могли получить доступ к классу Thread, предоставленному в .NET Framework. Добавьте эту строку в начало вашего файла .aspx / .ascx:
<%@ Import NameSpace="System.Threading" %>
или в VB.NET:
Imports System.Threading
Теперь для демонстрации, вот пример долгого метода работы. В реальной ситуации этот метод, скорее всего, будет выполнять такую задачу, как обработка веб-формы или выполнение трудоемкого запроса к базе данных.
Public Sub SomeLongMethod()
'your code that takes a while to execute
End Sub
Теперь, чтобы выполнить этот метод и не оставлять нашу веб-форму зависшей, мы запустим новый поток и позволим SomeLongMethod
Для этого у нас есть несколько вариантов. Техника, которую я буду использовать, — установить новый метод, который запустит наш новый поток. Вот пример функции запуска потока:
Public Sub SomeLongMethod_Thread()
'first, declare a new Thread, passing the constructor the address
'of SomeLongMethod. NOTE: SomeLongMethod can be replaced with your
'own method
Dim NewThread As Thread = New _
Thread(AddressOf SomeLongMethod)
'next we set the priority of our thread to lowest, setting
'the priority to a higher level can cause unexpected results.
NewThread.Priority = ThreadPriority.Lowest
'finally we start the thread executing
NewThread.Start()
End Sub
Вот и все! Все, что нам нужно сделать сейчас, это заменить наш вызов SomeLongMethod вызовом SomeLongMethod_Thread
Обычно мы перенаправляем пользователя на страницу результатов в конце метода SomeLongMethod_Thread
Однако в этом примере я не учел это во избежание путаницы — я продемонстрирую это в следующем примере, который иллюстрирует использование Threading в веб-приложении ASP.NET.
Использование Threading для перестройки строки
Первый файл, который мы рассмотрим, это default.aspx. Это будет страница, где мы получим 2 значения от пользователя и начнем новую тему. Второй файл, который мы рассмотрим, это страница результатов, где мы опрашиваем переменные Session, созданные в потоке, и показываем текущую статистику потока нашему пользователю. Я пройду через метод default.aspx по методу, а затем сделаю то же самое для страницы results.aspx. Исходный код этого файла доступен в конце этого урока.
ПРИМЕЧАНИЕ. Я предположил, что на вашем веб-сервере включены переменные сеанса. Если у вас отключены переменные сеанса или в вашем браузере отключены файлы cookie, результаты следующего примера не будут отображаться правильно.
Простой пример (default.aspx)
Давайте начнем с рассмотрения функции Page_Load
Sub Page_Load(ByVal sender As System.Object, ByVal e
As System.EventArgs)
SyncLock Session.SyncRoot
'here, we initialize 3 session variables to hold our results
Session("Complete") = False
Session("Status") = ""
Session("Phrase") = ""
End SyncLock
d Sub
В этом методе мы просто инициализируем 3 переменные сеанса, которые мы будем использовать в наших следующих нескольких методах. Session("Complete")
Когда поток завершится, мы установим для Session("Complete")
True
Переменная Session("Phrase")
Session("Status")
Теперь давайте посмотрим на наш метод перестройки фразы:
Sub PhraseBuilder()
Dim str As String = ""
Dim i As Integer = 0
Dim startTimeTicks As Long = 0
Dim strStartTime As String = ""
Dim totalSleepTime As Double = 0.0
'log our start time, in ticks, and in Long Date format
startTimeTicks = DateTime.Now.Ticks
strStartTime = "Thread Started: " & DateTime.Now
' get phrase
str = txtPhrase.Text
'convert users time from seconds to milliseconds
totalSleepTime = 1000.0
totalSleepTime = totalSleepTime * CInt(txtTotalThreadLife.Text)
totalSleepTime = (totalSleepTime / str.Length)
For i = 0 To str.Length - 1
'this method will put our thread to sleep for the specified
'number of milliseconds. without the sleep, this method would
'execute too fast to see the thread working.
Thread.Sleep(totalSleepTime)
'we use synclock to block any other thread from accessing
'session variables while we are changing their values.
SyncLock Session.SyncRoot
Session("Status") = "Thread is " & _
Format((i / (str.Length - 1)) * 100, "#0.00") & _
"% complete." & " - Time Elapsed: " & _
Format((DateTime.Now.Ticks - startTimeTicks) / 10000000 _
, "#0.00") & " sec. Target: " & txtTotalThreadLife.Text & _
".00 sec."
End SyncLock
SyncLock Session.SyncRoot
'rebuild phrase 1 letter at a time
Session("Phrase") &= str.Chars(i).ToString
End SyncLock
Next
'our method is complete, so set the Session variables
'accordingly
SyncLock Session.SyncRoot
Session("Status") = strStartTime & _
"<br>Thread Complete. End Time: " & DateTime.Now & "<br>"
Session("Complete") = True
End SyncLock
End Sub
Хорошо, теперь давайте рассмотрим этот метод немного. По сути, здесь мы заставляем метод, который в противном случае выполнялся бы быстро, запускаться по расписанию на основе пользовательского ввода. Это делается с помощью Thread.Sleep(ByVal millisecond as Integer)
Этот метод позволяет перевести поток в спящий режим на указанное количество миллисекунд. Этот метод Sleep
Другой интересный метод, который мы используем, — это использование метода Synclock
Синхронизация используется, чтобы заблокировать другие потоки от попытки получить тот же Synclock
Чтобы защитить переменные от одновременного доступа, нам нужно получить тот же Synclock, прежде чем мы получим доступ к переменным везде в коде. Это необходимо в многопоточном веб-приложении, чтобы гарантировать, что два метода не читают / записывают в одну и ту же переменную одновременно. Метод Synclock
Monitor.Enter(Me)
System.Threading Namespace
Осталось только два метода! Следующий метод, который мы рассмотрим, — это функция PhraseBuilder_Thread
Эта функция практически идентична примеру в начале статьи:
Sub PhraseBuilder_Thread()
'method to start our phrase builder method executing
'on a new thread.
Dim myThread As Thread = New Thread(AddressOf PhraseBuilder)
myThread.Priority = ThreadPriority.Lowest
'//start the new thread
myThread.Start()
'now redirect to the results page
Response.Redirect("results.aspx")
End Sub
Теперь осталось только вызвать наш метод PhraseBuilder_Thread
Вот краткий код:
Sub btnSubmit_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs)
'start PhraseBuilder thread...
PhraseBuilder_Thread()
End Sub
Простой пример (results.aspx)
Теперь посмотрим на страницу результатов. В основном наша страница результатов будет проверять состояние переменной Session("completed")
Page_Load
Вот функция Page_load
Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
'Put user code to initialize the page here
'check the value of Session("Completed"), if it is True, stop writing
If Session("Complete") <> True Then
'make sure session variables are enabled, if not warn user
If Session("Complete") <> False Then
'error with session variable, Session("Complete") is not
'True or False
lblComplete.Text = "Error with Session('Complete')"
Else
'set page to auto refresh page every 2 seconds, until thread is done
Response.Write("<META HTTP-EQUIV=Refresh CONTENT='2; URL='>")
SyncLock Session.SyncRoot
lblStatus.Text = Session("Status") & "<br>Processing. . ."
lblPhrase.Text = Session("Phrase")
lblComplete.Text = Session("Complete")
End SyncLock
End If
Else
'thread is complete, stop writing refresh tag, and display
'results
SyncLock Session.SyncRoot
lblStatus.Text = Session("Status")
lblPhrase.Text = Session("Phrase")
lblComplete.Text = Session("Complete")
End SyncLock
End If
End Sub
Эта функция Page_Load
Session("Complete")
Не стесняйтесь настраивать страницу результатов в соответствии с вашими потребностями, но я рекомендую проверить случай, когда переменная Session("Completed")
Обычно это происходит, когда переменные сеанса отключены или у вас отключены файлы cookie. Кроме того, вы можете удалить оператор Response.Write
В заключение
Ну, вот и все! Надеюсь, вы только что написали свое первое приложение ASP.NET с использованием потоков.
Использование потоков в нужных местах в ваших приложениях может значительно повысить производительность веб-сервера, а также предоставить пользователям гораздо лучший опыт работы в Интернете. Я надеюсь, вам понравился этот урок! Для получения дополнительной информации посетите: