- •Лекция 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()
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
Coffee.Cls Option Explicit Private Declare Function timeGetTime Lib "winmm.Dll" () As Long
' The Coffee object represents a different style of asynchronous notifications from those performed by the CoffeeMonitors. Instead of periodic notifications Coffee provides progress reports on a long task, and a completion event.
'
' The mechanism used for these notifications is to raise events. You could also use call-back methods, and in fact there are advantages to doing so. Call-backs would allow a component to deal intelligently with errors in the client, whereas events don't return client errors. This is discussed in "When to Use Events or Call-Backs for Notifications," in Books Online.
' Number of iterations to perform in the dummy task.
Private mlngIterations As Long
' XTimer is used to kick the long task off asynchronously.
Private WithEvents mwXTimer As XTimer
Event Progress(ByVal PercentDone As Single, ByRef Cancel As Boolean)
Event Complete(ByVal Canceled As Boolean)
' ThreadID returns the system thread ID of the thread the object was created on.
'
Public Property Get ThreadID() As Long
ThreadID = App.ThreadID
End Property
' NumberOnThread returns the number of Coffee objects running on this thread. This is just the value of the global data variable glngGlobalData, which Coffee objects increment in their Initialize events and decrement in their Terminate events.
' If MTCoffee was compiled with Thread Per Object, the only way for multiple objects' to share a thread (and the instance of global data associated with it) is if another Coffee has been created on this thread by calling GetCoffeeOnSameThread.
' If MTCoffee was compiled with a Thread Pool and the count of active objects exceeded the number of threads in the pool, then Coffee objects will be sharing threads.
'
Public Property Get NumberOnThread() As Long
NumberOnThread = glngGlobalData
End Property
' StartLongTask sets things up for the long dummy task. The task is actually started by a code-only XTimer that StartLongTask sets running.
'
Public Sub StartLongTask(ByVal Iterations As Long)
' This is a short circuit for testing call overhead. See CallAnotherCoffee.
If Iterations = 0 Then Exit Sub
'
' Store the size of the dummy task.
mlngIterations = Iterations
'
' Give the timer a short interval, and set it running just before returning.
mwXTimer.Interval = 55
mwXTimer.Enabled = True
End Sub
' GetCoffeeOnSameThread creates a new Coffee object on the same thread, simulating the effects of thread pooling. This can only be done internally, as explained in "How Object Creation Works in Visual Basic" in Books Online.
'
Public Function GetCoffeeOnSameThread() As Coffee
' All objects created using New will be on
' the creator's thread, even a new
' Coffee object.
Set GetCoffeeOnSameThread = New Coffee
End Function
' GetCoffeeOnNewThread creates a new Coffee object on a new thread, by calling CreateObject to create the new Coffee object. The difference between this and the internal creation done by GetCoffeeOnSameThread is explained in "How Object Creation Works in Visual Basic" in Books Online.'
' Note that this technique could be used to create objects on different threads that could communicate with each other, without the client having to pass one object a reference to the other (as CoffeeWatch does). If you experiment with this, remember that the overhead of marshaling calls between threads is almost as great as the overhead of marshaling calls across processes.
'