Статьи

Потоки в ASP.NET

В этом руководстве мы попытаемся пролить свет на тему многопоточности с использованием 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, прежде чем мы получим доступ к переменным везде в коде. Это необходимо в многопоточном веб-приложении, чтобы гарантировать, что два метода не читают / записывают в одну и ту же переменную одновременно. Метод SynclockMonitor.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_LoadSession("Complete") Не стесняйтесь настраивать страницу результатов в соответствии с вашими потребностями, но я рекомендую проверить случай, когда переменная Session("Completed") Обычно это происходит, когда переменные сеанса отключены или у вас отключены файлы cookie. Кроме того, вы можете удалить оператор Response.Write

В заключение

Ну, вот и все! Надеюсь, вы только что написали свое первое приложение ASP.NET с использованием потоков.

Использование потоков в нужных местах в ваших приложениях может значительно повысить производительность веб-сервера, а также предоставить пользователям гораздо лучший опыт работы в Интернете. Я надеюсь, вам понравился этот урок! Для получения дополнительной информации посетите: