ERROR: ModuleName, -2147418107, Automation error
It is illegal to call out while inside message filter.
I've read the Microsoft articles on how to prevent reentrancy into a call
while waiting for a COM control. I used the method of setting a flag to
prevent re-entry but the error continues to occure. The Technotes I've
located are VERY basic and I wonder if I'm mis-interpreting them. The
examples all show one Timer but I have many Timers in my app. I've created a
unique Flag for each timer in my code as in the example.
Code:
Private Sub Timer1_Timer()
Static flagA as Boolean
If Not flagA Then
flagA = True
Do Stuff Here
flagA = False
End If
End Sub
Private Sub Timer2_Timer()
Static flagB as Boolean
If Not flagB Then
flagB = True
Do Stuff Here
flagB = False
End If
End Sub
But the error still continues to occure I'm starting to think I need a
single global flag to prevent re-entry into ANY Timer. Not just re-entry
into the same Timer. For example
Code:
Public flag as Boolean
Private Sub Timer1_Timer()
If Not flag Then
flag = True
Do Stuff Here
flag = False
End If
End Sub
Private Sub Timer2_Timer()
Static flag as Boolean
If Not flag Then
flag = True
Do Stuff Here
flag = False
End If
End Sub
But the articles are not clear on exactly what needs to be prevented. Can
anyone familure with this please expand on the problem and its solution.
Thanks
Jim
...assuming the article you read was...
PRB: VB5.0 OLE Automation Error -2147418107 (80010005)
http://support.microsoft.com/kb/176399
...personally, I've never seen that problem. "Call Out" to what? An ActiveX
EXE (running in another process).
This isn't VBA, right?
How many timers? You can share timers by using State flags, etc.... believe
me... VB3/NT3 had specific limitations on the number of timers allowed (16?)
so sharing them became fairly common.
Hopefully you're not relying on the accuracy of a timer event for anything
critical. They're simply not accurate and weren't designed to be.
--
Ken Halter - MS-MVP-VB - Please keep all discussions in the groups..
In Loving Memory - http://www.vbsight.com/Remembrance.htm
>> I'm getting the following error in my application.
>>
>> ERROR: ModuleName, -2147418107, Automation error
>> It is illegal to call out while inside message filter.
>
> ...assuming the article you read was...
>
> PRB: VB5.0 OLE Automation Error -2147418107 (80010005)
> http://support.microsoft.com/kb/176399
>
>
> ...personally, I've never seen that problem. "Call Out" to what?
"In COM, no one can hear you scream."
The key question is, when in a Timer calling a control, do I prevent
re-entry into just that timer or do I need to prevent it from entering any
other timer? The article isn't clear to me.
Thanks
Jim
"Ken Halter" wrote:
> "JimMcGowanInlet" <JimMcGo...@discussions.microsoft.com> wrote in
> message news:246D595D-B3B1-4A98...@microsoft.com...
> > I'm getting the following error in my application.
> >
> > ERROR: ModuleName, -2147418107, Automation error
> > It is illegal to call out while inside message filter.
>
> ....assuming the article you read was...
>
> PRB: VB5.0 OLE Automation Error -2147418107 (80010005)
> http://support.microsoft.com/kb/176399
>
>
> ....personally, I've never seen that problem. "Call Out" to what? An ActiveX
"making calls to various controls both ocx and exe"
So, these are out of process exe's that return before the operation is
complete? (Async behavior)
This is a bit confusing because, by design, a timer shouldn't have the
ability to fire again before reaching its "End Sub" in its timer event
handler... which means there should be no need to protect against
reentrancy.
If you start a new project, drop a command button and a timer on the form
and run this code, you'll see that, even though the timer interval's set to
fire 100 times per second, it won't because it's waiting for the 'Pause' sub
to return.
'=================
Option Explicit
Private Sub Command1_Click()
Static bEnabled As Boolean
bEnabled = Not bEnabled
Timer1.Enabled = bEnabled
End Sub
Private Sub Form_Load()
Timer1.Enabled = False
Timer1.Interval = 10
End Sub
Private Sub Form_Unload(Cancel As Integer)
Timer1.Enabled = False
End Sub
Private Sub Timer1_Timer()
Debug.Print "Timer Fired", Timer
Call Pause(1)
End Sub
Private Sub Pause(Seconds As Single)
Dim f As Single
Dim l As Long
Debug.Print "PAUSE", Timer
f = Timer + Seconds 'fails if overlapping midnight
Do While Timer < f
l = l - 1
If l < 0 Then
l = 2500
DoEvents
End If
Loop
End Sub
'=================
But... if the flags seem to help, I'd set a "global" that prevented any
timers (no matter where they are) from doing their work, until I found out
what the real issue is.
Another option would be to dump the VB timer all together and use this
component....
TimerObj
Code-based timer object for use in non-windowed (or VBA) situations. OCX
included.
While you're there, this may be worth a peek
SyncEvts
Several ways to share events (timers, in this demo) amongst multiple
objects.
Ok... this is confusing <g> Their "Steps to Reproduce Behavior" don't
"Reproduce Behavior" here <g> It just works. (VB6/SP5)
The *only* difference in my test project(s) and theirs is.... I set up
Binary Compatibility... I have to... it's hard-wired into my brain... in
fact, my add-in does it for me every time I create a new component.
Other than that, I followed their steps to the letter.
If it *did* raise the error, the first thing I was going to try was:
'===============
Private Sub Timer1_Timer()
Timer1.Enabled = False '<--new
RetStr = t.Test(100000)
Text1.Text = RetStr
Timer1.Enabled = True '<--new
End Sub
'===============
Second thing I'd have tried was... placing a static flag in the external
procedure, instead of the timer event... but that's only possible if you're
in charge of everything (exe, ax-exe, etc) If these are 3rd party
components, your options are cut in half, right off the bat.
Another option (if you have source for everything) would be....
'===============
Private Sub Timer1_Timer()
Timer1.Enabled = False '<--disable the timer.... Period
RetStr = t.Test(100000)
Text1.Text = RetStr
End Sub
'===============
That disables the timer all together. You can add an event to the ActiveX
exe that fires when some operation is complete.... when that event fires,
you can re-enable the timer in the "operation_is_complete" event handler.
Thanks
Jim
You may want to consider dropping all but a single timer and maintaing a
queue of events and when they should run next. When the timer fires you
scan the queue, run any that are due and advance each run time to the next
interval. It's a little more work up front but is simpler and easier to
maintain and extend.