Skip to content

Commit c721dfc

Browse files
SND\joelleach_cpSND\joelleach_cp
authored andcommitted
ParallelFox: Added default error handler for workers when not in debug mode to prevent crashes.
Changed tmrCommand.Interval from 10 to 1 to speed up command processing. Worker.ReturnCursor() now adds ThreadID to temp filename to ensure it is unique. Critical section no longer required. Worker.ReturnCursor() now restores previous DBC properly when it is compiled into APP/EXE. Worker.EndCriticalSection() now makes sure named critical section has been started before trying to end it. WorkerProxy.Init(): Foreground window fix now only applies when running VFP IDE. Can cause problems when using VFP runtime. git-svn-id: https://vfpx.svn.codeplex.com/svn/ParallelFox@94128 81e6e737-5a20-4d0f-a97c-cb01297b46e0
1 parent 4e90403 commit c721dfc

3 files changed

Lines changed: 111 additions & 15 deletions

File tree

parallelfox.VCT

3.01 KB
Binary file not shown.

parallelfox.vca

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,82 @@ Pixels[END RESERVED6]
319319
[UNIQUEID] RESERVED
320320
[OBJNAME] events
321321

322+
[ RECORD]
323+
[PLATFORM] WINDOWS
324+
[UNIQUEID] _3CV0J32BY
325+
[CLASS] form
326+
[BASECLASS] form
327+
[OBJNAME] frmerrorlist
328+
[START PROPERTIES]
329+
AutoCenter = .T.
330+
Caption = "ParallelFox Worker Errors"
331+
DoCreate = .T.
332+
Height = 480
333+
Name = "frmerrorlist"
334+
Width = 640
335+
_memberdata = <VFPData><memberdata name="displayerror" display="DisplayError"/><memberdata name="cerrorlist" display="cErrorList"/></VFPData>
336+
cerrorlist =
337+
[END PROPERTIES]
338+
[START METHODS]
339+
PROCEDURE displayerror
340+
* Display error in list.
341+
Lparameters lnError, lcMethod, lnLine, lcMessage, lcCode
342+
Local lcErrorMsg
343+
344+
Text to lcErrorMsg TextMerge NoShow
345+
Error: <<lnError>>
346+
Message: <<lcMessage>>
347+
Method: <<lcMethod>>
348+
Line: <<lnLine>>
349+
<<Replicate("-",100)>>
350+
351+
EndText
352+
353+
ThisForm.cErrorList = ThisForm.cErrorList + lcErrorMsg
354+
* ThisForm.edtErrorList.Value = ThisForm.edtErrorList.Value + lcErrorMsg
355+
ThisForm.edtErrorList.Refresh()
356+
357+
358+
ENDPROC
359+
[END METHODS]
360+
[START RESERVED1]
361+
Class[END RESERVED1]
362+
[START RESERVED2]
363+
2[END RESERVED2]
364+
[START RESERVED3]
365+
*displayerror Display error in list.
366+
_memberdata XML Metadata for customizable properties
367+
cerrorlist List of errors.
368+
[END RESERVED3]
369+
[START RESERVED6]
370+
Pixels[END RESERVED6]
371+
372+
[ RECORD]
373+
[PLATFORM] WINDOWS
374+
[UNIQUEID] _3CV0J60T9
375+
[CLASS] editbox
376+
[BASECLASS] editbox
377+
[OBJNAME] edtErrorList
378+
[PARENT] frmerrorlist
379+
[START PROPERTIES]
380+
Anchor = 15
381+
ControlSource = "Thisform.cErrorList"
382+
Height = 478
383+
Left = 1
384+
Name = "edtErrorList"
385+
ReadOnly = .T.
386+
Top = 1
387+
Width = 638
388+
[END PROPERTIES]
389+
390+
[ RECORD]
391+
[PLATFORM] COMMENT
392+
[UNIQUEID] RESERVED
393+
[OBJNAME] frmerrorlist
394+
[START PROPERTIES]
395+
Arial, 0, 9, 5, 15, 12, 32, 3, 0
396+
[END PROPERTIES]
397+
322398
[ RECORD]
323399
[PLATFORM] WINDOWS
324400
[UNIQUEID] _2XO1B7PVN
@@ -662,11 +738,10 @@ Pixels[END RESERVED6]
662738
[BASECLASS] custom
663739
[OBJNAME] parpoolmgr
664740
[START PROPERTIES]
665-
666741
Name = "parpoolmgr"
667-
_memberdata =  1007<VFPData><memberdata name="ncpucount" display="nCPUCount"/><memberdata name="nworkercount" display="nWorkerCount"/><memberdata name="startworkers" display="StartWorkers"/><memberdata name="workers" display="Workers"/><memberdata name="nbusyworkers" display="nBusyWorkers"/><memberdata name="queuecommand" display="QueueCommand"/><memberdata name="processqueue" display="ProcessQueue"/><memberdata name="commandqueue" display="CommandQueue"/><memberdata name="ldebugmode" display="lDebugMode"/><memberdata name="stopworkers" display="StopWorkers"/><memberdata name="handleerror" display="HandleError"/><memberdata name="conerror" display="cOnError"/><memberdata name="clearqueue" display="ClearQueue"/><memberdata name="cworkercomprogid" display="cWorkerCOMProgID"/><memberdata name="cworkerclass" display="cWorkerClass"/><memberdata name="cworkerlibrary" display="cWorkerLibrary"/><memberdata name="nprocessing" display="nProcessing"/><memberdata name="setworkercount" display="SetWorkerCount"/></VFPData>
742+
_memberdata =  1115<VFPData><memberdata name="ncpucount" display="nCPUCount"/><memberdata name="nworkercount" display="nWorkerCount"/><memberdata name="startworkers" display="StartWorkers"/><memberdata name="workers" display="Workers"/><memberdata name="nbusyworkers" display="nBusyWorkers"/><memberdata name="queuecommand" display="QueueCommand"/><memberdata name="processqueue" display="ProcessQueue"/><memberdata name="commandqueue" display="CommandQueue"/><memberdata name="ldebugmode" display="lDebugMode"/><memberdata name="stopworkers" display="StopWorkers"/><memberdata name="handleerror" display="HandleError"/><memberdata name="conerror" display="cOnError"/><memberdata name="clearqueue" display="ClearQueue"/><memberdata name="cworkercomprogid" display="cWorkerCOMProgID"/><memberdata name="cworkerclass" display="cWorkerClass"/><memberdata name="cworkerlibrary" display="cWorkerLibrary"/><memberdata name="nprocessing" display="nProcessing"/><memberdata name="setworkercount" display="SetWorkerCount"/><memberdata name="displayerrors" display="DisplayErrors"/><memberdata name="oerrorlist" display="oErrorList"/></VFPData>
668743
commandqueue =
669-
conerror =
744+
conerror = This.DisplayErrors(nError, cMethod, nLine, cMessage, cCode)
670745
cworkerclass = WorkerMgr
671746
cworkercomprogid = ParallelFox.WorkerMgr
672747
cworkerlibrary = WorkerMgr.vcx
@@ -675,6 +750,7 @@ nbusyworkers = 0
675750
ncpucount = 0
676751
nprocessing = 0
677752
nworkercount = 0
753+
oerrorlist = .NULL.
678754
workers = .NULL.
679755
[END PROPERTIES]
680756
[START PROTECTED]
@@ -702,6 +778,17 @@ This.CommandQueue = CreateObject("Collection")
702778

703779
This.nProcessing = 0
704780
ENDPROC
781+
PROCEDURE displayerrors
782+
* Default error handler displays list of errors from workers.
783+
Lparameters lnError, lcMethod, lnLine, lcMessage, lcCode
784+
785+
If Vartype(This.oErrorList) <> "O" or IsNull(This.oErrorList)
786+
This.oErrorList = NewObject("frmErrorList", "ParallelFox.vcx")
787+
This.oErrorList.Show()
788+
EndIf
789+
790+
This.oErrorList.DisplayError(lnError, lcMethod, lnLine, lcMessage, lcCode)
791+
ENDPROC
705792
PROCEDURE handleerror
706793
* Global error handler. Set up with Parallel.OnError()
707794
Lparameters nError, cMethod, nLine, cMessage, cCode
@@ -914,6 +1001,7 @@ Class[END RESERVED1]
9141001
1[END RESERVED2]
9151002
[START RESERVED3]
9161003
*clearqueue Remove all pending commands from queue.
1004+
*displayerrors Default error handler displays list of errors from workers.
9171005
*handleerror Global Error Handler.
9181006
*processqueue Process command queue.
9191007
*queuecommand Add command to queue.
@@ -930,6 +1018,7 @@ nbusyworkers Number of workers currently processing commands.
9301018
ncpucount Number of logical processors on machine.
9311019
nprocessing Number of times ProcessQueue has been called.
9321020
nworkercount Number of workers. Defaults to CPU count.
1021+
oerrorlist Reference to error list form.
9331022
workers Workers collection.
9341023
[END RESERVED3]
9351024
[START RESERVED6]
@@ -949,7 +1038,7 @@ Pixels[END RESERVED6]
9491038
[START PROPERTIES]
9501039
Enabled = .F.
9511040
Height = 23
952-
Interval = 10
1041+
Interval = 1
9531042
Name = "tmrcommand"
9541043
Width = 23
9551044
_memberdata = <VFPData><memberdata name="processcommand" display="ProcessCommand"/><memberdata name="lprocessed" display="lProcessed"/><memberdata name="omanager" display="oManager"/></VFPData>
@@ -966,7 +1055,7 @@ Local loManager
9661055

9671056
This.Enabled = .f.
9681057
Doevents
969-
* Timer can fire more than once before it is enabled.
1058+
* Timer can fire more than once before it is disabled.
9701059
* Doevents usually prevents this from happening, but this code ensures it.
9711060
If This.lProcessed
9721061
Return
@@ -1070,11 +1159,13 @@ Debugout Time(0), Program(), cCriticalSectionName
10701159

10711160
* Find and release mutex
10721161
lnRow = Ascan(This._CriticalSections, cCriticalSectionName, 1, 0, 1, 8)
1073-
lnhMutex = This._CriticalSections[lnRow,2]
1074-
ReleaseMutex(lnhMutex)
1162+
If lnRow <> 0
1163+
lnhMutex = This._CriticalSections[lnRow,2]
1164+
ReleaseMutex(lnhMutex)
10751165

1076-
* Remove from array
1077-
Adel(This._CriticalSections, lnRow)
1166+
* Remove from array
1167+
Adel(This._CriticalSections, lnRow)
1168+
EndIf
10781169
ENDPROC
10791170
PROCEDURE isworker
10801171
* Returns .T. if currently running in Worker process.
@@ -1090,21 +1181,23 @@ cAlias = Evl(cAlias, Alias())
10901181
cDirectory = Evl(cDirectory, Sys(2023))
10911182

10921183
Do while .t.
1093-
lcTempName = Sys(2015)
1094-
* Use critical section to make sure multiple workers don't try to use the same filename
1095-
This.StartCriticalSection("ReturnCursor" + lcTempName)
1184+
* Sys(2015) may actually return the same value in separate processes
1185+
* Add ThreadID to the name to make sure it is unique across all workers
1186+
lcTempName = Sys(2015) + "_" + Transform(_VFP.ThreadId)
10961187
lcTempFile = Addbs(cDirectory) + lcTempName
10971188
If !File(lcTempFile + ".dbf") and !File(lcTempFile + ".dbc")
10981189
Exit
10991190
EndIf
1100-
This.EndCriticalSection("ReturnCursor" + lcTempName)
11011191
EndDo
11021192

11031193
* Create database to support long field names
11041194
lcDBC = Dbc()
1195+
If !DBused(lcDBC)
1196+
* Full path may not work if DBC is compiled into EXE/APP
1197+
lcDBC = JustStem(JustFname(lcDBC))
1198+
EndIf
11051199
lnCurrentArea = Select()
11061200
Create Database (lcTempFile)
1107-
This.EndCriticalSection("ReturnCursor" + lcTempName)
11081201

11091202
* Copy cursor to temp table
11101203
Select (cAlias)
@@ -1295,7 +1388,10 @@ EndIf
12951388

12961389
* In Windows XP and earlier, main process can lose focus when
12971390
* instantiating COM EXE. Make sure we keep it.
1298-
If GetForegroundWindow() <> lhWndForeground
1391+
* This issue apparently only affects IDE, and can cause wrong window
1392+
* to get focus at runtime if workers started when main VFP window is not visible.
1393+
* So, only applying to IDE. May revisit if issue presents itself at runtime or other scenarios.
1394+
If _VFP.StartMode = 0 and GetForegroundWindow() <> lhWndForeground
12991395
DECLARE INTEGER SetForegroundWindow IN user32 INTEGER hwnd
13001396
SetForegroundWindow(lhWndForeground)
13011397
EndIf

parallelfox.vcx

327 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)