- •Лекция 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()
Private Sub cmdShortOnly_Click()
lstResults.Clear
CancelAll = False
mintHowManyShort = 10
tmrShort.Interval = 250
tmrShort.Enabled = True
End Sub
' Run a long task, then run short tasks serially while it's running.
Private Sub cmdShortLong_Click()
Dim cft As CoffeeTracker
lstResults.Clear
CancelAll = False
Set cft = NewTracker(macfe(1).ThreadID, LONGTASKSIZE)
Set cft.Coffee = macfe(1)
Call macfe(1).StartLongTask(LONGTASKSIZE)
'
' Line up some short tasks to run (one every quarter second) while task runs.
mintHowManyShort = 10
tmrShort.Enabled = True
tmrShort.Interval = 250
End Sub
' Start N long tasks (1 - 9), then run a series of short tasks.
Private Sub cmdNLong_Click()
Dim intCt As Integer
Dim cft As CoffeeTracker
lstResults.Clear
CancelAll = False
For intCt = 1 To CLng("0" & txtN)
Set cft = NewTracker(macfe(intCt).ThreadID, LONGTASKSIZE)
Set cft.Coffee = macfe(intCt)
Call macfe(intCt).StartLongTask(LONGTASKSIZE)
Next
'
' Line up some short tasks to run while the long ones run.
mintHowManyShort = 10 + CLng("0" & txtN)
tmrShort.Enabled = True
tmrShort.Interval = 250
End Sub
' Compare the call overhead for calls to an object on the same thread, vs. calls to an object on another thread.
'
Private Sub cmdXThread_Click()
Dim cfeSame As Coffee
Dim cfeNew As Coffee
cmdXThread.Caption = "Working..."
cmdXThread.Enabled = False
' Create a Coffee object on another thread.
Set cfeNew = macfe(10).GetCoffeeOnNewThread
' In case of thread pooling; except in the degenerate case of one thread in the pool, this should get a different thread the second time.
If cfeNew.ThreadID = macfe(10).ThreadID Then
Set cfeNew = macfe(10).GetCoffeeOnNewThread
If cfeNew.ThreadID = macfe(10).ThreadID Then
MsgBox "Unable to run comparison between same-thread and cross-thread calls; can't get an object on another thread."
Exit Sub
End If
End If
'
' Create a Coffee object on the same thread.
Set cfeSame = macfe(10).GetCoffeeOnSameThread
' Use the newly created coffee objects to perform the test.
MsgBox "Same thread: " & macfe(10).CallAnotherCoffee(cfeSame) & " sec/call" & vbCrLf _
& "Cross-thread: " & macfe(10).CallAnotherCoffee(cfeNew) & " sec/call"
cmdXThread.Caption = "Cross-Thread Overhead"
cmdXThread.Enabled = True
'
' The Coffee objects created for this test are terminated when cfeNew and cfeSame go out of scope at the end of this procedure.
End Sub
' List the thread IDs of the Coffee objects created when this form loaded.
Private Sub cmdIDs_Click()
Dim intCt As Integer
lstResults.Clear
For intCt = 1 To 10
lstResults.AddItem macfe(intCt).ThreadID _
& " (" & macfe(intCt).NumberOnThread & " on thread)"
Next
End Sub
' Create a series of Coffee objects, each on its own thread. (If you recompile MTCoffee with a thread pool
' less than 10, some of these will share thread and global state.)
Private Sub Form_Load()
Dim intCt As Integer
For intCt = 1 To 10
Set macfe(intCt) = New Coffee
Next
Form1.cmdMT.Enabled = True
Form1.cmdMT.MousePointer = vbDefault
End Sub
Private Sub Text1_KeyPress(KeyAscii As Integer)
Select Case KeyAscii
Case 48 To 57, 8
Case Else
Beep
KeyAscii = 0
End Select
End Sub
' Provide unique keys for CoffeeTrackers.
Private Function NewKey() As String
Static lngLastKey As Long
lngLastKey = lngLastKey + 1
NewKey = "K" & lngLastKey
End Function
' Add a new CoffeeTracker. Properly speaking, this should be a method of a CoffeeTrackers collection class.
Private Function NewTracker(ByVal ThreadID As Long, _
ByVal Size As Long) As CoffeeTracker
Dim cft As New CoffeeTracker
'
' Cache the thread ID of the Coffee object the tracker will be keeping track of.
cft.ThreadID = ThreadID
'
' Set the size of the task assigned to the Coffee object the tracker will track.
cft.Size = Size
'
' Give the tracker a unique key for the collection.
cft.ID = NewKey
'
' Put the new tracker into a collection.
CoffeeTrackers.Add cft, cft.ID
'
' Return a reference to the new tracker.
Set NewTracker = cft
End Function
' Timer is used to start a series of short tasks, at regular intervals, using one Coffee object (that is, a single thread).
' Before starting a new task, it checks to see whether the preceding task is done.
'
' If you run MTCoffee in the development environment, comment out the code that checks for preceding task completion.