Главная опасность (общие данные)
До настоящего момента рассматривался единственный безопасный случай использования потоков – наши потоки не изменяли общих данных. Если разрешить изменение общих данных, потенциальные ошибки начинают плодиться в геометрической прогрессии и избавить от них программу становится гораздо труднее. С другой стороны, если запретить модификацию общих данных разными потоками, многопоточное программирование .NET практически не будет отличаться от ограниченных возможностей VB6.
Вашему вниманию предлагается небольшая программа, которая демонстрирует возникающие проблемы, не углубляясь в излишние подробности. В этой программе моделируется дом, в каждой комнате которого установлен термостат. Если температура на 5 и более градусов по Фаренгейту (около 2.77 градусов по Цельсию) меньше положенной, мы приказываем системе отопления повысить температуру на 5 градусов; в противном случае температура повышается только на 1 градус. Если текущая температура больше либо равна заданной, изменение не производится. Регулировка температуры в каждой комнате осуществляется отдельным потоком с 200-миллисекундной задержкой. Основная работа выполняется следующим фрагментом:
If mHouse.HouseTemp < mHouse.MAX_TEMP = 5 Then Try Thread.Sleep(200) Catch tie As ThreadlnterruptedException ' Пассивное ожидание было прервано Catch e As Exception ' Другие исключения End Try mHouse.HouseTemp +- 5 ' И т.д.
Ниже приведен полный исходный текст программы.
1 Option Strict On 2 Imports System.Threading 3 Module Modulel 4 Sub Main() 5 Dim myHouse As New House(l0) 6 Console. ReadLine() 7 End Sub 8 End Module 9 Public Class House 10 Public Const MAX_TEMP As Integer = 75 11 Private mCurTemp As Integer = 55 12 Private mRooms() As Room 13 Public Sub New(ByVal numOfRooms As Integer) 14 ReDim mRooms(numOfRooms = 1) 15 Dim i As Integer 16 Dim aThreadStart As Threading.ThreadStart 17 Dim aThread As Thread 18 For i = 0 To numOfRooms -1 19 Try 20 mRooms(i)=NewRoom(Me, mCurTemp,CStr(i) &"throom") 21 aThreadStart – New ThreadStart(AddressOf _ mRooms(i).CheckTempInRoom) 22 aThread =New Thread(aThreadStart) 23 aThread.Start() 24 Catch E As Exception 25 Console.WriteLine(E.StackTrace) 26 End Try 27 Next 28 End Sub 29 Public Property HouseTemp()As Integer 30. Get 31 Return mCurTemp 32 End Get 33 Set(ByVal Value As Integer) 34 mCurTemp = Value 35 End Set 36 End Property 37 End Class 38 Public Class Room 39 Private mCurTemp As Integer 40 Private mName As String 41 Private mHouse As House 42 Public Sub New(ByVal theHouse As House, ByVal temp As Integer, ByVal roomName As String) 43 mHouse = theHouse 44 mCurTemp = temp 45 mName = roomName 46 End Sub 47 Public Sub CheckTempInRoom() 48 ChangeTemperature() 49 End Sub 50 Private Sub ChangeTemperature() 51 Try 52 If mHouse.HouseTemp < mHouse.MAX_TEMP -5 Then 53 Thread.Sleep(200) 54 mHouse.HouseTemp + -5 55 Console.WriteLine("Am in " & Me.mName & _ 56 ".Current temperature is "&mHouse.HouseTemp) 57. Elself mHouse.HouseTemp < mHouse.MAX_TEMP Then 58 Thread.Sleep(200) 59 mHouse.HouseTemp += 1 60 Console.WriteLine("Am in " & Me.mName & _ 61 ".Current temperature is " & mHouse.HouseTemp) 62 Else 63 Console.WriteLine("Am in " & Me.mName & _ 64 ".Current temperature is " & mHouse.HouseTemp) 65 ' Ничего не делать, температура нормальная 66 End If 67 Catch tae As ThreadlnterruptedException 68 ' Пассивное ожидание было прервано 69 Catch e As Exception 70 ' Другие исключения 71 End Try 72 End Sub 73 End Class