Совместная работа с данными по мере их создания
23 Public Property TheWeek() As Integer 24 Get 25 Return mweek 26 End Get 27 Set(ByVal Value As Integer) 28 mweek – Value 29 End Set 30 End Property 31 Public Property OurMoney() As Integer 32 Get 33 Return mMoney 34 End Get 35 Set(ByVal Value As Integer) 36 mMoney =Value 37 End Set 38 End Property 39 Public Sub Produce() 40 Thread.Sleep(500) 41 Do 42 Monitor.Enter(Me) 43 Do While Me.OurMoney > 0 44 Monitor.Wait(Me) 45 Loop 46 Me.OurMoney =1000 47 Monitor.PulseAll(Me) 48 Monitor.Exit(Me) 49 Loop 50 End Sub 51 Public Sub Consume() 52 MsgBox("Am in consume thread") 53 Do 54 Monitor.Enter(Me) 55 Do While Me.OurMoney = 0 56 Monitor.Wait(Me) 57 Loop 58 Console.WriteLine("Dear parent I just spent all your " & _ money in week " & TheWeek) 59 TheWeek += 1 60 If TheWeek = 21 *52 Then System.Environment.Exit(0) 61 Me.OurMoney =0 62 Monitor.PulseAll(Me) 63 Monitor.Exit(Me) 64 Loop 65 End Sub 66 End Class
Метод StartltsLife (строки 13-22) осуществляет подготовку к запуску потоков Produce и Consume. Самое главное происходит в потоках Produce (строки 39-50) и Consume (строки 51-65). Процедура Sub Produce проверяет наличие денег, и если деньги есть, переходит в очередь ожидания. В противном случае родитель генерирует деньги (строка 46) и оповещает объекты в очереди ожидания об изменении ситуации. Учтите, что вызов Pulse-Pulse All вступает в силу лишь при снятии блокировки командой Monitor.Exit.
И наоборот, процедура Sub Consume проверяет наличие денег, и если денег нет – оповещает об этом ожидающего родителя. Строка 60 просто завершает программу по прошествии 21 условного года; вызов System.Environment.Exit(0) является .NET-аналогом команды End (команда End тоже поддерживается, но в отличие от System.Environment.Exit она не позволяет вернуть код завершения операционной системе).
Примечание
Потоки, переведенные в очередь ожидания, должны быть освобождены другими частями вашей программы. Именно по этой причине мы предпочитаем использовать PulseAll вместо Pulse. Поскольку заранее неизвестно, какой именно поток будет активизирован при вызове Pulse, при относительно небольшом количестве потоков в очереди с таким же успехом можно вызвать PulseAll.