- •Лекция 13
- •XTimers.Vbp 5
- •Обзор задачи Coffee Sample Application
- •XTimers.Vbp
- •XTimerSupport.Bas
- •Private Type xtimerinfo ' Hungarian xti
- •Public Sub TimerProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal lngSysTime As Long)
- •If maxti(intCt).BlnReentered Then Exit Sub
- •Public Sub EndTimer(ByVal xt As xTimer)
- •Public Sub Scrub()
- •Public Property Get Interval() As Long
- •Public Property Let Interval(ByVal NewInterval As Long)
- •Public Sub RaiseTick()
- •Private Sub Class_Terminate()
- •MtCoffee.Vbp modMt.Bas Option Explicit
- •Public glngGlobalData As Long
- •Coffee.Bas
- •Option Explicit
- •Private Declare Function timeGetTime Lib "winmm.Dll" () As Long
- •Private mlngIterations As Long
- •Public Property Get NumberOnThread() As Long
- •Public Sub StartLongTask(ByVal Iterations As Long)
- •Public Function GetCoffeeOnSameThread() As Coffee
- •Public Function GetCoffeeOnNewThread() As Coffee
- •If blnCancel Then
- •Coffee.Cls Option Explicit Private Declare Function timeGetTime Lib "winmm.Dll" () As Long
- •Private mlngIterations As Long
- •Public Property Get NumberOnThread() As Long
- •Public Sub StartLongTask(ByVal Iterations As Long)
- •Public Function GetCoffeeOnSameThread() As Coffee
- •Public Function GetCoffeeOnNewThread() As Coffee
- •If blnCancel Then
- •Public Property Get CoffeeMonitor() As CoffeeMonitor
- •If gCoffeeMonitor Is Nothing Then
- •CoffeeMonitor.Cls Option Explicit
- •Private WithEvents mwXTimer As xTimer
- •Event CoffeeReady() Private Sub Class_Initialize()
- •Private Sub Class_Terminate()
- •Private Sub mwXTimer_Tick()
- •Connector2.Cls Option Explicit
- •Public Property Get CoffeeMonitor2() As CoffeeMonitor2
- •CoffeeMonitor2 Option Explicit
- •Private maicnClients() As iCoffeeNotify
- •Public Sub TellMeReady(ByVal icn As iCoffeeNotify)
- •Public Sub CeaseCallBacks(ByVal icn As iCoffeeNotify)
- •Private Sub mwXTimer_Tick()
- •ICoffeeNotify.Cls
- •Public ThreadId As Long
- •Private Sub mwCoffee_Progress(ByVal PercentDone As Single, Cancel As Boolean)
- •Private Sub cmdCallBacks_Click()
- •Private Sub cmdMt_Click()
- •Private Sub Form_Unload(Cancel As Integer)
- •Private Sub mwcmnEvents_CoffeeReady()
- •FrmThread.Frm
- •Private Sub cmdCancel_Click()
- •Private Sub cmdShortOnly_Click()
- •Private Sub cmdShortLong_Click()
- •Private Sub cmdNLong_Click()
- •Private Sub cmdXThread_Click()
- •Private Sub cmdIDs_Click()
- •Private Sub tmrShort_Timer()
Public Function GetCoffeeOnNewThread() As Coffee
' Create as if by external client.
Set GetCoffeeOnNewThread = CreateObject("MTCoffee.Coffee")
End Function
' CallAnotherCoffee gives a rough measure of cross-thread call overhead. Pass it a Coffee object on another thread, or on the same thread, and compare the results; the method makes dummy calls to StartLongTask, so that it's essentially measuring only the call overhead.
'
Public Function CallAnotherCoffee(ByVal cfe As Coffee) As Double
Const TRIES = 10000
Dim timeStart As Long
Dim timeEnd As Long
Dim lngTries As Long
timeStart = timeGetTime
For lngTries = 1 To TRIES
cfe.StartLongTask 0
Next
timeEnd = timeGetTime
' Return seconds (ss.mmm) per call. (This will give an incorrect result if you happen to run CallAnotherCoffee just as the system timer is rolling over to zero.)
CallAnotherCoffee = ((CDbl(timeEnd) - timeStart) / 1000#) / TRIES
End Function
Private Sub Class_Initialize()
' Increment the global count (that is, for this thread) of Coffee objects.
glngGlobalData = glngGlobalData + 1
' Create a timer object.
Set mwXTimer = New XTimer
End Sub
Private Sub Class_Terminate()
' Decrement the global count (that is, for this thread) of Coffee objects.
glngGlobalData = glngGlobalData - 1
' Free the timer object.
Set mwXTimer = Nothing
End Sub
Private Sub mwXTimer_Tick()
' First thing, turn off the timer.
mwXTimer.Enabled = False
Call LongTask
End Sub
' The dummy task.
'
Private Sub LongTask()
Dim dblDummy As Double
Dim lngCt As Long
Dim sngNextMark As Single
Dim blnCancel As Boolean
' For small transactions, don't bother to call back while running.
If mlngIterations < 100000 Then
sngNextMark = 1!
Else
sngNextMark = 0.1!
End If
' This is just a time-waster.
For lngCt = 1 To mlngIterations
' If this were a real application, a unit of work would be done here. You may find it interesting to replace this processor-intensive activity with one that waits on the system a lot, such as calls to a database on another machine, or reading a very large file.
' Throughput on a single-processor workstation is far greater when most threads are blocked, waiting for file input or the result of a database call.
dblDummy = 3033.14159 * 2081.14159 * 1138.14159
'
If CDbl(lngCt) / mlngIterations > sngNextMark Then
RaiseEvent Progress(sngNextMark, blnCancel)
If blnCancel Then
' If the client is tired of waiting and wants the task canceled, raise the Complete event with True (canceled).
RaiseEvent Complete(True)
Exit Sub
End If
sngNextMark = sngNextMark + 0.1!
End If
Next
' On successful completion, raise the Complete event with False (not canceled).
RaiseEvent Complete(False)
End Sub
Coffee2.vbp
Module1.bas
Option Explicit
' For an overview of this sample application, search online Help for Coffee. AboutCof.Txt, in the Related Documents folder of CoffWat2.vbp, also contains information about the sample.
' gCoffeeMonitor holds a reference to the shared CoffeeMonitor object. When a client accesses the CoffeeMonitor property of a Connector object, the Property Get returns this reference. (See the Connector class module.)
Public gCoffeeMonitor As CoffeeMonitor
' gCoffeeMonitor2 holds a reference to the shared CoffeeMonitor2 object. When a client accesses the CoffeeMonitor2 property of a Connector2 object, the Property Get returns this reference. (See the Connector2 class module.)
Public gCoffeeMonitor2 As CoffeeMonitor2
Connector.cls:
Option Explicit
' > For an overview of this sample application, search online Help for Coffee. AboutCof.Txt, in the Related Documents folder of CoffWat2.vbp, also contains information about the sample.
' Connector class-
' The Connector allows multiple clients to share a single CoffeeMonitor object. The Connector class has its Instancing property set to MultiUse, so each client can create its own Connector. Each of the Connector objects returns a reference to the single shared CoffeeMonitor object, so all the clients share the same CoffeeMonitor. (See the CoffeeMonitor property, below.)
' If you read "Creating an ActiveX Exe Component," in Books Online, you'll notice a difference: This version of Connector doesn't have a 'use count' that determines when gCoffeeMonitor should be set to Nothing. There's no need for Initialize event code to increment the use count, or Terminate event code to decrement and test the use count.
' This solves a bug described in the topic "Using the Shared CoffeeMonitor" in the chapter mentioned above. For an explanation of why the use count isn't needed, and how this fixes the bug, see the CoffeeMonitor class module.
' CoffeeMonitor property always returns the single global reference to the shared instance of CoffeeMonitor (which is created the first time a client requests a CoffeeMonitor).