472,118 Members | 1,173 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,118 software developers and data experts.

Serializing a request for an ASP page containing COM objects

Max
Due to the behaviour of a particular COM object, I need to ensure that a
request for a particular ASP page is finalized before another request for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?

If not, can IIS be configured to use seperate processes to satisfy requests
for a nominated ASP page?

Thanks in advance.

Max
Aug 1 '06 #1
47 2978

Max wrote:
Due to the behaviour of a particular COM object, I need to ensure that a
request for a particular ASP page is finalized before another request for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?

If not, can IIS be configured to use seperate processes to satisfy requests
for a nominated ASP page?
As far as I'm aware, you can only specify process isolation on a
per-application basis. This procedure varies with the version of IIS
you're using.

Here's the procedure for version 6 (my version):
http://www.microsoft.com/technet/pro....mspx?mfr=true

Aug 1 '06 #2

"Max" <ng*****@pfxcorp.comwrote in message
news:44**********************@per-qv1-newsreader-01.iinet.net.au...
Due to the behaviour of a particular COM object, I need to ensure that a
request for a particular ASP page is finalized before another request for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?

If not, can IIS be configured to use seperate processes to satisfy
requests for a nominated ASP page?

Thanks in advance.
Hi Max, as long as you don't have more web servers that serve the same
website (ie url like www.yoursite.com) you can lock your page, through a
Mutex object.
A mutex, enables multiple processes on the same machine to synced single
access to a single event.

Aug 1 '06 #3
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure
that a request for a particular ASP page is finalized before another
request for the page is processed. Does IIS have a way to ensure that
subsequent requests will be queued until the current request is
completed?
If not, can IIS be configured to use seperate processes to satisfy
requests for a nominated ASP page?
If the object is not free-threaded, storing it in Application may accomplish
your goal. This is the reason we constantly advise against storing ADO
objects (such as Connections) in Application: they are apartment-threaded so
they can only service one thread at a time, in effect serializing all uses
of the object.

--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
Aug 1 '06 #4

"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:Oh**************@TK2MSFTNGP03.phx.gbl...
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure
that a request for a particular ASP page is finalized before another
request for the page is processed. Does IIS have a way to ensure that
subsequent requests will be queued until the current request is
completed?
If not, can IIS be configured to use seperate processes to satisfy
requests for a nominated ASP page?
If the object is not free-threaded, storing it in Application may
accomplish
your goal. This is the reason we constantly advise against storing ADO
objects (such as Connections) in Application: they are apartment-threaded
so
they can only service one thread at a time, in effect serializing all uses
of the object.
It's a nice idea but the application object simply disallows
apartment-threaded objects.

--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"


Aug 1 '06 #5

"Bobbo" <ro******@gmail.comwrote in message
news:11*********************@75g2000cwc.googlegrou ps.com...
>
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure that a
request for a particular ASP page is finalized before another request
for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?

If not, can IIS be configured to use seperate processes to satisfy
requests
for a nominated ASP page?

As far as I'm aware, you can only specify process isolation on a
per-application basis. This procedure varies with the version of IIS
you're using.

Here's the procedure for version 6 (my version):
http://www.microsoft.com/technet/pro....mspx?mfr=true
>
On it's own it doesn't help serialise access to the page. It may be
possible to tweak the application metadata to allow only one worker thread
then only one request into the application can be processed at a time.

One approach might be to enable debugging. That limits the app to a single
thread but care needs to be taken that any configured debugger doesn't block
operation (e.g. Dr Watson style debugging is ok but script debugger will
just hang the process if there is an error).

If there is only one CPU then setting AspProcessorThreadMax to 1 might also
do it.

Anthony.
Aug 1 '06 #6
Anthony Jones wrote:
"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:Oh**************@TK2MSFTNGP03.phx.gbl...
>Max wrote:
>>Due to the behaviour of a particular COM object, I need to ensure
that a request for a particular ASP page is finalized before another
request for the page is processed. Does IIS have a way to ensure
that subsequent requests will be queued until the current request is
completed?
If not, can IIS be configured to use seperate processes to satisfy
requests for a nominated ASP page?
If the object is not free-threaded, storing it in Application may
accomplish your goal. This is the reason we constantly advise
against storing ADO objects (such as Connections) in Application:
they are apartment-threaded so they can only service one thread at a
time, in effect serializing all uses of the object.

It's a nice idea but the application object simply disallows
apartment-threaded objects.

I'm not sure I'm following your point. Could you expand on what you mean by
"disallows"?

--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
Aug 1 '06 #7
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure that a
request for a particular ASP page is finalized before another request for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?
If not, can IIS be configured to use seperate processes to satisfy requests
for a nominated ASP page?
Max
Use the Application.Lock and Application.Unlock methods:
....
Application.Lock
....
'Critical section of code.
....
Application.Unlock
....

While there may be several copies of that page executing, the lock
ensures that only one is be executing the critical section of code at
any time. If a page finds the Application object locked, it will wait.

It isn't necessary to store anything in the Application object. You're
merely using the Application object's methods as a mutex to enforce
serialized access to the critical section of code.

Of course, serializing access will result in queuing and will slow
response. So minimize the time and resources utilized in the critical
section of code, enter it as late as possible and exit it as soon as
possible.
Aug 2 '06 #8
Max

"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Anthony Jones wrote:
>"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:Oh**************@TK2MSFTNGP03.phx.gbl...
>>Max wrote:
Due to the behaviour of a particular COM object, I need to ensure
that a request for a particular ASP page is finalized before another
request for the page is processed. Does IIS have a way to ensure
that subsequent requests will be queued until the current request is
completed?
If not, can IIS be configured to use seperate processes to satisfy
requests for a nominated ASP page?

If the object is not free-threaded, storing it in Application may
accomplish your goal. This is the reason we constantly advise
against storing ADO objects (such as Connections) in Application:
they are apartment-threaded so they can only service one thread at a
time, in effect serializing all uses of the object.

It's a nice idea but the application object simply disallows
apartment-threaded objects.

I'm not sure I'm following your point. Could you expand on what you mean
by "disallows"?

--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
My thanks to Bobbo, Anthony, Egbert and Bob for their input.

Unfortunately I may have some input on the setup of our clients web server
but not on the machine it runs on. As I cannot guarantee a single
processor, I cannot use your "set AspProcessorThreadMax to 1" suggestion.

I am still looking at the suggestion to enable debugging although the
possibility of the process just hanging on the customers site would not be
acceptable.

I am interested in Anthonys suggestion to "tweak the application metadata to
allow only one worker thread" but am not sure which metadata values I would
need to set to accomplish this.

The COM object that I am using is marked as single threaded and doesn't
appear to have any protection when IIS makes overlapping requests for the
ASP page using it. We may be able to use a mutex but performance would be an
issue.

I have been looking into the use of a web garden (in IIS6) which appears to
offer multiple processes on the same application. Do you think that using a
web garden would be useful in this situation? Perhaps in combination with
allowing only one worker thread as suggested by Anthony?

Thanks in advance,

Max
Aug 2 '06 #9

"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Anthony Jones wrote:
"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:Oh**************@TK2MSFTNGP03.phx.gbl...
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure
that a request for a particular ASP page is finalized before another
request for the page is processed. Does IIS have a way to ensure
that subsequent requests will be queued until the current request is
completed?
If not, can IIS be configured to use seperate processes to satisfy
requests for a nominated ASP page?

If the object is not free-threaded, storing it in Application may
accomplish your goal. This is the reason we constantly advise
against storing ADO objects (such as Connections) in Application:
they are apartment-threaded so they can only service one thread at a
time, in effect serializing all uses of the object.
It's a nice idea but the application object simply disallows
apartment-threaded objects.
I'm not sure I'm following your point. Could you expand on what you mean
by
"disallows"?
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

ASP just errors saying that assigning this sort of object into the
application object is disallowed.
You can only assign free-threaded objects into the application object.

Assigning into the session is allowed but that will affiliate the session ID
with a thread and all requests containing that session cookie will only ever
be serviced be the affiliated thread (this doesn't help in the OP's case).
Over time this will mean requests will queue up to be serviced even though
worker threads are available because their affiliated thread is busy with
another request. What's really annoying is that even if the object
reference is only fleeting stored in the session object and then removed the
thread will still remain affiliated.

--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"


Aug 2 '06 #10

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure that a
request for a particular ASP page is finalized before another request
for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?
If not, can IIS be configured to use seperate processes to satisfy
requests
for a nominated ASP page?
Max
Use the Application.Lock and Application.Unlock methods:
...
Application.Lock
...
'Critical section of code.
...
Application.Unlock
...

While there may be several copies of that page executing, the lock
ensures that only one is be executing the critical section of code at
any time. If a page finds the Application object locked, it will wait.

It isn't necessary to store anything in the Application object. You're
merely using the Application object's methods as a mutex to enforce
serialized access to the critical section of code.

Of course, serializing access will result in queuing and will slow
response. So minimize the time and resources utilized in the critical
section of code, enter it as late as possible and exit it as soon as
possible.
It should be pointed out that this will affect all uses of application
locks. If the application is to contain other pages (not connected with the
problem in question) use application locks these pages will be affected
also.

IOW the Application object itself can be used as a single global mutex.
Personally I prefer Egbert's solution.
Aug 2 '06 #11
Anthony Jones wrote:
>I'm not sure I'm following your point. Could you expand on what you
mean by "disallows"?

<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

ASP just errors saying that assigning this sort of object into the
application object is disallowed.
Interesting. I've never tried that so I never encountered that error. I have
just confirmed what you are saying, however.

You can only assign free-threaded objects into the application object.
ADO objects aren't free-threaded (unless marked as such in the registry) ...
why does IIS allow people to store ADO recordsets and connections in
application?
--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
Aug 2 '06 #12

"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:uz**************@TK2MSFTNGP05.phx.gbl...
Anthony Jones wrote:
I'm not sure I'm following your point. Could you expand on what you
mean by "disallows"?
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

ASP just errors saying that assigning this sort of object into the
application object is disallowed.

Interesting. I've never tried that so I never encountered that error. I
have
just confirmed what you are saying, however.

You can only assign free-threaded objects into the application object.

ADO objects aren't free-threaded (unless marked as such in the registry)
....
why does IIS allow people to store ADO recordsets and connections in
application?
ADO uses a free threaded marshaller in this case. Hence the object
reference the application stores is in fact a free threaded proxy for the
ADO object rather than a reference to the object itself. Of course as soon
as anything tries to call a method on the proxy the calling thread will
block while the call is marshalled across to the thread that originally
created the object. If that thread is busy with another request (or some
other marshalled call from yet another thread) then the call blocks.
Therefore as you say it is not a good idea to store ADO objects in the
application object.
>
--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"


Aug 2 '06 #13
Anthony Jones wrote:
>ADO objects aren't free-threaded (unless marked as such in the
registry) ... why does IIS allow people to store ADO recordsets and
connections in application?

ADO uses a free threaded marshaller in this case. Hence the object
reference the application stores is in fact a free threaded proxy for
the ADO object rather than a reference to the object itself. Of
course as soon as anything tries to call a method on the proxy the
calling thread will block while the call is marshalled across to the
thread that originally created the object. If that thread is busy
with another request (or some other marshalled call from yet another
thread) then the call blocks. Therefore as you say it is not a good
idea to store ADO objects in the application object.

OK, that makes sense ... thanks. We never stop learning.

--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.
Aug 2 '06 #14
Anthony Jones wrote:
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>
You failed to lock the Application object in your example, which should
read:
<%
Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
Application.Lock
Set Application("x") = o
Application.UnLock
%>
Assuming, of course, that the object is free-threaded.

Aug 2 '06 #15
Anthony Jones wrote:
<snipped>
>
It should be pointed out that this will affect all uses of application
locks. If the application is to contain other pages (not connected with the
problem in question) use application locks these pages will be affected
also. IOW the Application object itself can be used as a single global mutex.
As clearly documented by Microsoft.
Personally I prefer Egbert's solution.
Certainly Egbert's is the most general solution. But no debugged code
was provided.

In it's favor, my suggestion is quick, easy to apply, clearly works as
designed by Microsoft and the tested code is provided above.

My suggestion will work until that mutex method is written and debugged.
Or even forever, if need be. [Yes, billions and billions of ASP pages
running until the _end_ _of_ _time_, bwaahaahaaahaaaa!]

My suggestion is certainly better than the two you suggested earlier:
1-enable debugging or
2-setting AspProcessorThreadMax to 1
which were both very amusing. Thanks for the laugh.

All in all, I think you're embarrassed that you missed this most obvious
suggestion, one designed by Microsoft. Reason I say that is that, in the
example you gave where you stored an object into the Application object,
you neglected to lock and unlock the Application object, a common newbie
error. Just a guess; I could be wrong, of course.
Aug 2 '06 #16
Michael D. Kersey wrote:
Anthony Jones wrote:
<snipped>
>>
It should be pointed out that this will affect all uses of
application locks. If the application is to contain other pages (not
connected with the problem in question) use application locks these
pages will be affected also. IOW the Application object itself can
be used as a single global mutex.

As clearly documented by Microsoft.
>Personally I prefer Egbert's solution.

Certainly Egbert's is the most general solution. But no debugged code
was provided.

In it's favor, my suggestion is quick, easy to apply, clearly works as
designed by Microsoft and the tested code is provided above.

My suggestion will work until that mutex method is written and
debugged. Or even forever, if need be. [Yes, billions and billions of
ASP pages running until the _end_ _of_ _time_, bwaahaahaaahaaaa!]

My suggestion is certainly better than the two you suggested earlier:
1-enable debugging or
2-setting AspProcessorThreadMax to 1
which were both very amusing. Thanks for the laugh.

All in all, I think you're embarrassed that you missed this most
obvious suggestion, one designed by Microsoft. Reason I say that is
that, in the example you gave where you stored an object into the
Application object, you neglected to lock and unlock the Application
object, a common newbie error. Just a guess; I could be wrong, of
course.
Is there some history between you two here? This is verging on being
insulting (perhaps even crossing the line), and Im not sure the insult
was called for. From what I could see, Anthony was expressing a
preference for a technique, not disparaging yours, which he did
acknowledge would accomplish the OP's purpose.

I am sure that Anthony is aware of the need to lock Application, and
simply left it out of his example because he was sure I was aware of the
need to do that as well.
--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.
Aug 2 '06 #17

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Anthony Jones wrote:
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

You failed to lock the Application object in your example, which should
read:
What happens if you don't call Lock, Unlock?
<%
Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
Application.Lock
Set Application("x") = o
Application.UnLock
%>

Assuming, of course, that the object is free-threaded.

Aug 2 '06 #18
Anthony Jones wrote:
IOW the Application object itself can be used as a single global
mutex. Personally I prefer Egbert's solution.
How does one create a mutex in vbscript without using
application.lock...unlock?
I was not aware that thread could be created in scripting ...
--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.
Aug 2 '06 #19

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
Anthony Jones wrote:
<snipped>

It should be pointed out that this will affect all uses of application
locks. If the application is to contain other pages (not connected with
the
problem in question) use application locks these pages will be affected
also. IOW the Application object itself can be used as a single global
mutex.
>
As clearly documented by Microsoft.
Personally I prefer Egbert's solution.

Certainly Egbert's is the most general solution. But no debugged code
was provided.

In it's favor, my suggestion is quick, easy to apply, clearly works as
designed by Microsoft and the tested code is provided above.

My suggestion will work until that mutex method is written and debugged.
Or even forever, if need be. [Yes, billions and billions of ASP pages
running until the _end_ _of_ _time_, bwaahaahaaahaaaa!]

My suggestion is certainly better than the two you suggested earlier:
1-enable debugging or
2-setting AspProcessorThreadMax to 1
which were both very amusing. Thanks for the laugh.
I agree. I was just enjoying thinking up mad ways to achieve this like I
said Egbert's is best if although better yet would be to design out the
requirement altogether.
All in all, I think you're embarrassed that you missed this most obvious
suggestion, one designed by Microsoft. Reason I say that is that, in the
example you gave where you stored an object into the Application object,
you neglected to lock and unlock the Application object, a common newbie
error. Just a guess; I could be wrong, of course.
It is of course possible that you are wrong. I've posted a question in
another branch perhaps you can enlighten this 'newbie' rather than just
being obnoxious. (Is that spelt right?)
Aug 2 '06 #20

"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:e7**************@TK2MSFTNGP05.phx.gbl...
Michael D. Kersey wrote:
Anthony Jones wrote:
<snipped>
>
It should be pointed out that this will affect all uses of
application locks. If the application is to contain other pages (not
connected with the problem in question) use application locks these
pages will be affected also. IOW the Application object itself can
be used as a single global mutex.
As clearly documented by Microsoft.
Personally I prefer Egbert's solution.
Certainly Egbert's is the most general solution. But no debugged code
was provided.

In it's favor, my suggestion is quick, easy to apply, clearly works as
designed by Microsoft and the tested code is provided above.

My suggestion will work until that mutex method is written and
debugged. Or even forever, if need be. [Yes, billions and billions of
ASP pages running until the _end_ _of_ _time_, bwaahaahaaahaaaa!]

My suggestion is certainly better than the two you suggested earlier:
1-enable debugging or
2-setting AspProcessorThreadMax to 1
which were both very amusing. Thanks for the laugh.

All in all, I think you're embarrassed that you missed this most
obvious suggestion, one designed by Microsoft. Reason I say that is
that, in the example you gave where you stored an object into the
Application object, you neglected to lock and unlock the Application
object, a common newbie error. Just a guess; I could be wrong, of
course.

Is there some history between you two here?
None that I''m aware of although I'll admit I am woefully lacking in the
social graces department so perhaps my blunt sounding posts may have upset
him at some point.
>This is verging on being
insulting (perhaps even crossing the line), and Im not sure the insult
was called for.
Probably was. I was criticising his suggestion which clearly superior to any
of mine. ;)
>From what I could see, Anthony was expressing a
preference for a technique, not disparaging yours, which he did
acknowledge would accomplish the OP's purpose.

I am sure that Anthony is aware of the need to lock Application, and
simply left it out of his example because he was sure I was aware of the
need to do that as well.
Indeed it wasn't really needed for point being demonstrated.
>
--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.


Aug 2 '06 #21
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
>Anthony Jones wrote:
>><%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

You failed to lock the Application object in your example, which should
read:

What happens if you don't call Lock, Unlock?
Any other request can change the value of Application("x") outside of the
current ASP thread, effectively breaking the serialisation on the initial
calls. Using Lock will prevent it being changed by another request until the
Unlock method is called.

Dan
Aug 2 '06 #22
Daniel wrote to Anthony Jones on Wed, 2 Aug 2006 16:35:11 +0100:
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
>>Anthony Jones wrote:
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

You failed to lock the Application object in your example, which should
read:

What happens if you don't call Lock, Unlock?

Any other request can change the value of Application("x") outside of the
current ASP thread, effectively breaking the serialisation on the initial
calls. Using Lock will prevent it being changed by another request until
the Unlock method is called.

Dan
Oops, forgot to also mention that the ASP page that get the Lock on first
will cause all the others to wait until Unlock is called, they won't just
skip the setting of the Application variable.

Dan
Aug 2 '06 #23

"Bob Barrows [MVP]" <re******@NOyahoo.SPAMcomwrote in message
news:u3**************@TK2MSFTNGP02.phx.gbl...
Anthony Jones wrote:
IOW the Application object itself can be used as a single global
mutex. Personally I prefer Egbert's solution.

How does one create a mutex in vbscript without using
application.lock...unlock?
None that I know of but creating a small component to do this shouldn't be
too hard. If I really needed it it's what I'd do but not without vigorously
trying to avoid it altogether.
I was not aware that thread could be created in scripting ...
No thread creation is needed.

--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.


Aug 2 '06 #24

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Anthony Jones wrote:
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

You failed to lock the Application object in your example, which should
read:
What happens if you don't call Lock, Unlock?

Any other request can change the value of Application("x") outside of the
current ASP thread, effectively breaking the serialisation on the initial
calls. Using Lock will prevent it being changed by another request until
the
Unlock method is called.

Dan

Thanks for taking the time to answer my question. However I have to be
honest and admit I was being facetious.

Apart from the fact the that with or without a lock the code fails miserably
anyway why does simply assigning a value to the application object require a
lock? With a lock anything that wants to change it will, as soon as the
lock is released, so why bother?

Now this:-

Application("myNumber") = Application("myNumber") + 1

or the substance thereof does need a lock. In the time between reading
myNumber and re-assigning it back it is probably undesirable that anything
else is reading and assigning it.

Or is there something I'm missing?

Anthony.


Aug 2 '06 #25
Max

"Anthony Jones" <An*@yadayadayada.comwrote in message
news:eE**************@TK2MSFTNGP04.phx.gbl...
>
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
>Max wrote:
Due to the behaviour of a particular COM object, I need to ensure that
a
request for a particular ASP page is finalized before another request
for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?
If not, can IIS be configured to use seperate processes to satisfy
requests
for a nominated ASP page?
Max
Use the Application.Lock and Application.Unlock methods:
...
Application.Lock
...
'Critical section of code.
...
Application.Unlock
...

While there may be several copies of that page executing, the lock
ensures that only one is be executing the critical section of code at
any time. If a page finds the Application object locked, it will wait.

It isn't necessary to store anything in the Application object. You're
merely using the Application object's methods as a mutex to enforce
serialized access to the critical section of code.

Of course, serializing access will result in queuing and will slow
response. So minimize the time and resources utilized in the critical
section of code, enter it as late as possible and exit it as soon as
possible.

It should be pointed out that this will affect all uses of application
locks. If the application is to contain other pages (not connected with
the
problem in question) use application locks these pages will be affected
also.

IOW the Application object itself can be used as a single global mutex.
Personally I prefer Egbert's solution.

Thanks everyone for their answers.

I have been considering your suggestions and the possible consequences of
locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or critical
section) which would prevent multiple requests through the same process AND
use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance penalty of
a global lock. Any thoughts, experiences or that won't work because ...
would be appreciated.

Thanks
Max
Aug 3 '06 #26

"Max" <ng*****@pfxcorp.comwrote in message
news:44***********************@per-qv1-newsreader-01.iinet.net.au...
>
"Anthony Jones" <An*@yadayadayada.comwrote in message
news:eE**************@TK2MSFTNGP04.phx.gbl...

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Max wrote:
Due to the behaviour of a particular COM object, I need to ensure
that
a
request for a particular ASP page is finalized before another request
for
the page is processed. Does IIS have a way to ensure that subsequent
requests will be queued until the current request is completed?
If not, can IIS be configured to use seperate processes to satisfy
requests
for a nominated ASP page?
Max

Use the Application.Lock and Application.Unlock methods:
...
Application.Lock
...
'Critical section of code.
...
Application.Unlock
...

While there may be several copies of that page executing, the lock
ensures that only one is be executing the critical section of code at
any time. If a page finds the Application object locked, it will wait.

It isn't necessary to store anything in the Application object. You're
merely using the Application object's methods as a mutex to enforce
serialized access to the critical section of code.

Of course, serializing access will result in queuing and will slow
response. So minimize the time and resources utilized in the critical
section of code, enter it as late as possible and exit it as soon as
possible.
It should be pointed out that this will affect all uses of application
locks. If the application is to contain other pages (not connected with
the
problem in question) use application locks these pages will be affected
also.

IOW the Application object itself can be used as a single global mutex.
Personally I prefer Egbert's solution.
Thanks everyone for their answers.

I have been considering your suggestions and the possible consequences of
locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
section) which would prevent multiple requests through the same process
AND
use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance penalty
of
a global lock. Any thoughts, experiences or that won't work because ...
would be appreciated.
Now your requirements are less clear. The problem is we don't know why you
need to serialise access to the COM object. Perhaps you could elaborate?

It appears from the above (correct me if I'm wrong) that you are a happy for
the same page to run concurrently if running in different processes, this
suggests to me that you are trying to use a component which is not thread
safe.
Thanks
Max


Aug 3 '06 #27
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:
>
"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
>Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Anthony Jones wrote:
<%
>
Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>
Set Application("x") = o
>
%>

You failed to lock the Application object in your example, which should
read:

What happens if you don't call Lock, Unlock?

Any other request can change the value of Application("x") outside of the
current ASP thread, effectively breaking the serialisation on the initial
calls. Using Lock will prevent it being changed by another request until
the
>Unlock method is called.

Dan
Thanks for taking the time to answer my question. However I have to be
honest and admit I was being facetious.
After I'd posted my reply I did wonder, as you seemed to understand from
replies in other branches that you know what Lock/Unlock does. I didn't see
that a followup from me was needed though.
Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the application
object require a lock? With a lock anything that wants to change it will,
as soon as the lock is released, so why bother?
Because by assigning an apartment/single threaded object into it you force
ASP into serialising all further page processing. The Lock/Unlock ensures
that if there are a couple of concurrent requests when the application is
first hit that they are then processed serially - if you don't use
Lock/Unlock there's a chance, albeit very slim, that a few requests might
get executed concurrently as they attempt to initialise the Application
variable simultaneously.
Now this:-

Application("myNumber") = Application("myNumber") + 1

or the substance thereof does need a lock. In the time between reading
myNumber and re-assigning it back it is probably undesirable that anything
else is reading and assigning it.

Or is there something I'm missing?
Maybe the thread topic of serialising the requests?

Dan
Aug 3 '06 #28

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Anthony Jones wrote:
<%

Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")

Set Application("x") = o

%>

You failed to lock the Application object in your example, which
should
>>read:

What happens if you don't call Lock, Unlock?

Any other request can change the value of Application("x") outside of
the
current ASP thread, effectively breaking the serialisation on the
initial
calls. Using Lock will prevent it being changed by another request
until
the
Unlock method is called.

Dan
Thanks for taking the time to answer my question. However I have to be
honest and admit I was being facetious.

After I'd posted my reply I did wonder, as you seemed to understand from
replies in other branches that you know what Lock/Unlock does. I didn't
see
that a followup from me was needed though.
Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the application
object require a lock? With a lock anything that wants to change it
will,
as soon as the lock is released, so why bother?

Because by assigning an apartment/single threaded object into it you force
ASP into serialising all further page processing
Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is the
point I was illustrating.
>The Lock/Unlock ensures
that if there are a couple of concurrent requests when the application is
first hit that they are then processed serially - if you don't use
Lock/Unlock there's a chance, albeit very slim, that a few requests might
get executed concurrently as they attempt to initialise the Application
variable simultaneously.
OK what happens if an application variable is updated simultaneously by
concurrently running ASP pages? Bear in mind the the Application object is
thread safe. Having considered what actually happens, in what way is it
different from when Lock/Unlock is used?

Have a look at this:-

Application("thing1") = AValue
Application("thing2") = AnotherValue

There is a reason why you might want this protected by Lock/Unlock what is
it?

Now in another page we have this the application variables are just being
read:-

AValue = Application("thing1")
AnotherValue = Application("thing2")

does this need Lock/Unlock?
Now this:-

Application("myNumber") = Application("myNumber") + 1

or the substance thereof does need a lock. In the time between reading
myNumber and re-assigning it back it is probably undesirable that
anything
else is reading and assigning it.

Or is there something I'm missing?

Maybe the thread topic of serialising the requests?

Dan


Aug 3 '06 #29
Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:
>
"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
>Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:
>>"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl.. .
>Anthony Jones wrote:
>><%
>>>
>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>
>>Set Application("x") = o
>>>
>>%>
>>
>You failed to lock the Application object in your example, which
should
>>>>>read:
>
What happens if you don't call Lock, Unlock?

Any other request can change the value of Application("x") outside of
the
>>>current ASP thread, effectively breaking the serialisation on the
initial
>>>calls. Using Lock will prevent it being changed by another request
until
>>the
Unlock method is called.

Dan

Thanks for taking the time to answer my question. However I have to be
honest and admit I was being facetious.

After I'd posted my reply I did wonder, as you seemed to understand from
replies in other branches that you know what Lock/Unlock does. I didn't
see
>that a followup from me was needed though.
>>Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the application
object require a lock? With a lock anything that wants to change it
will,
>>as soon as the lock is released, so why bother?

Because by assigning an apartment/single threaded object into it you
force ASP into serialising all further page processing

Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is the
point I was illustrating.
I've stored ADO apartment threaded objects in it before. I won't ever do it
again. That was the first mistake I made on my first ASP application.
>The Lock/Unlock ensures
that if there are a couple of concurrent requests when the application is
first hit that they are then processed serially - if you don't use
Lock/Unlock there's a chance, albeit very slim, that a few requests might
get executed concurrently as they attempt to initialise the Application
variable simultaneously.

OK what happens if an application variable is updated simultaneously by
concurrently running ASP pages? Bear in mind the the Application object
is thread safe. Having considered what actually happens, in what way is
it different from when Lock/Unlock is used?
I guess my understanding of threading is rusty and outdated. I'll have to go
back and read up, and concede that I'm probably wrong. Putting values like
strings into the Application object wasn't the point of my reply - storing
references to objects that are not free threaded was.

Dan
Aug 3 '06 #30

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:Oh*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:e8**************@TK2MSFTNGP06.phx.gbl...
Anthony Jones wrote:
><%
>>
>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>
>Set Application("x") = o
>>
>%>
>
You failed to lock the Application object in your example, which
should
>>>>read:

What happens if you don't call Lock, Unlock?

Any other request can change the value of Application("x") outside of
the
>>current ASP thread, effectively breaking the serialisation on the
initial
>>calls. Using Lock will prevent it being changed by another request
until
>the
Unlock method is called.

Dan

Thanks for taking the time to answer my question. However I have to
be
>honest and admit I was being facetious.

After I'd posted my reply I did wonder, as you seemed to understand
from
replies in other branches that you know what Lock/Unlock does. I didn't
see
that a followup from me was needed though.

Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the application
object require a lock? With a lock anything that wants to change it
will,
>as soon as the lock is released, so why bother?

Because by assigning an apartment/single threaded object into it you
force ASP into serialising all further page processing
Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is
the
point I was illustrating.

I've stored ADO apartment threaded objects in it before. I won't ever do
it
again. That was the first mistake I made on my first ASP application.
Nope it just looks that way. What you've been storing a free threaded proxy
to the ADO object.
The Lock/Unlock ensures
that if there are a couple of concurrent requests when the application
is
first hit that they are then processed serially - if you don't use
Lock/Unlock there's a chance, albeit very slim, that a few requests
might
get executed concurrently as they attempt to initialise the Application
variable simultaneously.
OK what happens if an application variable is updated simultaneously by
concurrently running ASP pages? Bear in mind the the Application object
is thread safe. Having considered what actually happens, in what way is
it different from when Lock/Unlock is used?

I guess my understanding of threading is rusty and outdated. I'll have to
go
back and read up, and concede that I'm probably wrong. Putting values like
strings into the Application object wasn't the point of my reply - storing
references to objects that are not free threaded was.
I don't think you're wrong necessarily just unsure why you are right. ;)
Dan


Aug 3 '06 #31
Anthony wrote on Thu, 3 Aug 2006 14:02:34 +0100:
>
"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:Oh*************@TK2MSFTNGP06.phx.gbl...
>Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:
>>"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
>Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>>
>>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
>>news:e8**************@TK2MSFTNGP06.phx.gbl.. .
>>>Anthony Jones wrote:
>>>><%
>>>>>
>>>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>>>
>>>>Set Application("x") = o
>>>>>
>>>>%>
>>>>
>>>You failed to lock the Application object in your example, which
should
>>>read:
>>>
>>What happens if you don't call Lock, Unlock?
>>
>Any other request can change the value of Application("x") outside of
the
>current ASP thread, effectively breaking the serialisation on the
initial
>calls. Using Lock will prevent it being changed by another request
until
the
>Unlock method is called.
>>
>Dan
>>
Thanks for taking the time to answer my question. However I have to
be
>>>>honest and admit I was being facetious.

After I'd posted my reply I did wonder, as you seemed to understand
from
>>>replies in other branches that you know what Lock/Unlock does. I didn't
see
that a followup from me was needed though.

Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the application
object require a lock? With a lock anything that wants to change it
will,
as soon as the lock is released, so why bother?

Because by assigning an apartment/single threaded object into it you
force ASP into serialising all further page processing

Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is
the
>>point I was illustrating.

I've stored ADO apartment threaded objects in it before. I won't ever do
it
>again. That was the first mistake I made on my first ASP application.
Nope it just looks that way. What you've been storing a free threaded
proxy to the ADO object.
OK, but that still, according to MS, will result in the ASP requests being
serialised, right? In which case there is some marshalling going on to the
apartment threaded objects that the proxy is referencing, and given that the
proxy is free threaded doesn't this lend weight to the possibility that
having two simultaneous requests trying to assign an ADO (or other apartment
threaded object) into the Application object could cause those two requests
to not be serialised? Using Lock/Unlock would force the serialisation by
preventing one of those ASP pages from trying to add a reference to the
object to the Application object while the other request was doing so. Or
would the fact that the object is apartment threaded anyway mean that the
proxy on one request would be queued behind the other for access to the
object?

Dan

Dan
Aug 3 '06 #32

"Anthony Jones" <An*@yadayadayada.comwrote in message
news:Oh**************@TK2MSFTNGP06.phx.gbl...
>
"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:
>
"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
>Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>>
>>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
>>news:e8**************@TK2MSFTNGP06.phx.gbl...
>>>Anthony Jones wrote:
>>>><%
>>>>>
>>>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>>>
>>>>Set Application("x") = o
>>>>>
>>>>%>
>>>>
>>>You failed to lock the Application object in your example, which
should
>>>read:
>>>
>>What happens if you don't call Lock, Unlock?
>>
>Any other request can change the value of Application("x") outside of
the
>current ASP thread, effectively breaking the serialisation on the
initial
>calls. Using Lock will prevent it being changed by another request
until
the
>Unlock method is called.
>>
>Dan
>>
Thanks for taking the time to answer my question. However I have to
be
honest and admit I was being facetious.
After I'd posted my reply I did wonder, as you seemed to understand from
replies in other branches that you know what Lock/Unlock does. I didn't
see
that a followup from me was needed though.
Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the application
object require a lock? With a lock anything that wants to change it
will,
as soon as the lock is released, so why bother?
Because by assigning an apartment/single threaded object into it you
force
ASP into serialising all further page processing

Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is the
point I was illustrating.
The Lock/Unlock ensures
that if there are a couple of concurrent requests when the application
is
first hit that they are then processed serially - if you don't use
Lock/Unlock there's a chance, albeit very slim, that a few requests
might
get executed concurrently as they attempt to initialise the Application
variable simultaneously.

OK what happens if an application variable is updated simultaneously by
concurrently running ASP pages? Bear in mind the the Application object is
thread safe.
Since the application object is thread safe it isn't going let multiple
threads modify it's internal structures at the same time. Hence any
simultaneous attempts to modify the contents will cause one thread to
continue and the others to block until the one thread is finished. Each
thread will make consistent changes one after the other. The last one to
make changes wins as it were.
>Having considered what actually happens, in what way is it
different from when Lock/Unlock is used?
It isn't different. Updates to a single value in the application object are
serialised whether you use lock or not.
Have a look at this:-

Application("thing1") = AValue
Application("thing2") = AnotherValue

There is a reason why you might want this protected by Lock/Unlock what is
it?
If it is important that the value assigned from AValue is consistent with
AnotherValue then this needs a Lock otherwise it is possible that in between
assigning AValue and AnotherValue the thread could be bumped off the CPU and
another request to the same page makes different changes. Once the original
thread resumes it will assign AnotherValue and the application will end up
with AnotherValue from this thread and AValue from the other thread.
>
Now in another page we have this the application variables are just being
read:-

AValue = Application("thing1")
AnotherValue = Application("thing2")

does this need Lock/Unlock?
Assuming that AValue and AnotherValue need to be consistent with when they
were assigned then yes it needs a lock. For pretty much the same reason as
above.
Now this:-
>
Application("myNumber") = Application("myNumber") + 1
>
or the substance thereof does need a lock. In the time between
reading
myNumber and re-assigning it back it is probably undesirable that
anything
else is reading and assigning it.
>
Or is there something I'm missing?
Maybe the thread topic of serialising the requests?

Dan


Aug 3 '06 #33

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:OT**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 14:02:34 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:Oh*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:uK*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>
>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
>news:e8**************@TK2MSFTNGP06.phx.gbl. ..
>>Anthony Jones wrote:
>>><%
>>>>
>>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>>
>>>Set Application("x") = o
>>>>
>>>%>
>>>
>>You failed to lock the Application object in your example, which
should
>>read:
>>
>What happens if you don't call Lock, Unlock?
>
Any other request can change the value of Application("x") outside
of
>the
current ASP thread, effectively breaking the serialisation on the
initial
calls. Using Lock will prevent it being changed by another request
until
the
Unlock method is called.
>
Dan
>
Thanks for taking the time to answer my question. However I have to
be
>>>honest and admit I was being facetious.

After I'd posted my reply I did wonder, as you seemed to understand
from
>>replies in other branches that you know what Lock/Unlock does. I
didn't
>see
that a followup from me was needed though.

Apart from the fact the that with or without a lock the code fails
miserably anyway why does simply assigning a value to the
application
>>>object require a lock? With a lock anything that wants to change it
will,
as soon as the lock is released, so why bother?

Because by assigning an apartment/single threaded object into it you
force ASP into serialising all further page processing

Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is
the
>point I was illustrating.

I've stored ADO apartment threaded objects in it before. I won't ever
do
it
again. That was the first mistake I made on my first ASP application.
Nope it just looks that way. What you've been storing a free threaded
proxy to the ADO object.

OK, but that still, according to MS, will result in the ASP requests being
serialised, right?
If you mean that all requests to ASP will from now on go to the same thread
and have to queue one after the other then no. I'm not sure you meant that
though.
In which case there is some marshalling going on to the
apartment threaded objects that the proxy is referencing,
Yep when any worker thread (and there can still be many) attempts to use the
stored object any call to the object will be marshalled to the original
thread that created the object.

Ultimately this can result in a massive cross thread marshalling to this one
poor thread that pretty much is being asked to do all the applications ADO
activity single handed. Not good. ;)
and given that the
proxy is free threaded doesn't this lend weight to the possibility that
having two simultaneous requests trying to assign an ADO (or other
apartment
threaded object) into the Application object could cause those two
requests
to not be serialised?
The proxy is free threaded so two requests can attempt to make a call on it
simutaneously, the proxy will happily create two simultaneous cross thread
calls but one will block until the other completes.
Using Lock/Unlock would force the serialisation by
preventing one of those ASP pages from trying to add a reference to the
object to the Application object while the other request was doing so.
Not using a lock does the same. Only one thread can make a modification to
the application object at the same time with or without a lock.

The proxy assigned first will then immediately be released as the proxy from
the second gets assigned. The last thread to make the assignment becomes
the victim of an onslaught of calls from other threads wanting the services
of the ADO object it has. The other ADO objects that had fleeting been
assigned will be destroyed when their requests complete or before.
>Or
would the fact that the object is apartment threaded anyway mean that the
proxy on one request would be queued behind the other for access to the
object?
Only one proxy gets stored.
Dan

Dan


Aug 3 '06 #34
Anthony wrote on Thu, 3 Aug 2006 14:47:23 +0100:
>
"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:OT**************@TK2MSFTNGP02.phx.gbl...
>Anthony wrote on Thu, 3 Aug 2006 14:02:34 +0100:
>>"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:Oh*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl.. .
>Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:
>>
>>"Daniel Crichton" <ms****@worldofspack.comwrote in message
>>news:uK*************@TK2MSFTNGP06.phx.gbl. ..
>>>Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>>>>
>>>>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
>>>>news:e8**************@TK2MSFTNGP06.phx.gbl ...
>>>>>Anthony Jones wrote:
>>>>>><%
>>>>>>>
>>>>>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>>>>>
>>>>>>Set Application("x") = o
>>>>>>>
>>>>>>%>
>>>>>>
>>>>>You failed to lock the Application object in your example, which
should
>>>>>read:
>>>>>
>>>>What happens if you don't call Lock, Unlock?
>>>>
>>>Any other request can change the value of Application("x") outside
of
>>>>the
>>>current ASP thread, effectively breaking the serialisation on the
initial
>>>calls. Using Lock will prevent it being changed by another request
until
>>the
>>>Unlock method is called.
>>>>
>>>Dan
>>>>
>>Thanks for taking the time to answer my question. However I have to
be
>>honest and admit I was being facetious.
>>
>After I'd posted my reply I did wonder, as you seemed to understand
from
>replies in other branches that you know what Lock/Unlock does. I
didn't
>>>>see
>that a followup from me was needed though.
>>
>>Apart from the fact the that with or without a lock the code fails
>>miserably anyway why does simply assigning a value to the
application
>>>>>>object require a lock? With a lock anything that wants to change it
will,
>>as soon as the lock is released, so why bother?
>>
>Because by assigning an apartment/single threaded object into it you
>force ASP into serialising all further page processing
>
Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which is
the
point I was illustrating.

I've stored ADO apartment threaded objects in it before. I won't ever
do
>>it
again. That was the first mistake I made on my first ASP application.

Nope it just looks that way. What you've been storing a free threaded
proxy to the ADO object.

OK, but that still, according to MS, will result in the ASP requests
being serialised, right?

If you mean that all requests to ASP will from now on go to the same
thread and have to queue one after the other then no. I'm not sure you
meant that though.
I felt sure years ago when I first started ASP development that MS had
published an article that said exactly this. However all I can find now are
articles about how it will serialise only the specific Session, not the
Application, and cause ADO objects to remain memory resident (which was the
other reason I very quickly changed my programming back then).

Looks like I've learnt something new again, but still reinforced the
recommendations I give to customers that putting ADO objects (and I tend to
apply the same rule to all objects) in the Session/Application object is a
bad idea.

Dan
Aug 3 '06 #35
Daniel wrote to Anthony Jones on Thu, 3 Aug 2006 15:23:39 +0100:
Anthony wrote on Thu, 3 Aug 2006 14:47:23 +0100:
>"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:OT**************@TK2MSFTNGP02.phx.gbl...
>>Anthony wrote on Thu, 3 Aug 2006 14:02:34 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:Oh*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:
>
>"Daniel Crichton" <ms****@worldofspack.comwrote in message
>news:O2**************@TK2MSFTNGP02.phx.gbl. ..
>>Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:
>>>
>>>"Daniel Crichton" <ms****@worldofspack.comwrote in message
>>>news:uK*************@TK2MSFTNGP06.phx.gbl.. .
>>>>Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>>>>>
>>>>>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
>>>>>news:e8**************@TK2MSFTNGP06.phx.gb l...
>>>>>>Anthony Jones wrote:
>>>>>>><%
>>>>>>>>
>>>>>>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>>>>>>
>>>>>>>Set Application("x") = o
>>>>>>>>
>>>>>>>%>
>>>>>>>
>>>>>>You failed to lock the Application object in your example, which
>should
>>>>>>read:
>>>>>>
>>>>>What happens if you don't call Lock, Unlock?
>>>>>
>>>>Any other request can change the value of Application("x") outside
of
>>>>>the
>>>>current ASP thread, effectively breaking the serialisation on the
>initial
>>>>calls. Using Lock will prevent it being changed by another request
>until
>>>the
>>>>Unlock method is called.
>>>>>
>>>>Dan
>>>>>
>>>Thanks for taking the time to answer my question. However I have
>>>to
be
>>>honest and admit I was being facetious.
>>>
>>After I'd posted my reply I did wonder, as you seemed to understand
from
>>replies in other branches that you know what Lock/Unlock does. I
didn't
>>>>>see
>>that a followup from me was needed though.
>>>
>>>Apart from the fact the that with or without a lock the code fails
>>>miserably anyway why does simply assigning a value to the
application
>>>>>>>object require a lock? With a lock anything that wants to change
>>>it
>will,
>>>as soon as the lock is released, so why bother?
>>>
>>Because by assigning an apartment/single threaded object into it you
>>force ASP into serialising all further page processing
>>
>Try my code. Add Lock/Unlock if you like. It doesn't work. The
>application object will not store references to STA objects. Which
>is
the
>point I was illustrating.
>
I've stored ADO apartment threaded objects in it before. I won't ever
do
>>>it
again. That was the first mistake I made on my first ASP application.
>
Nope it just looks that way. What you've been storing a free threaded
proxy to the ADO object.

OK, but that still, according to MS, will result in the ASP requests
being serialised, right?

If you mean that all requests to ASP will from now on go to the same
thread and have to queue one after the other then no. I'm not sure you
meant that though.
Now I remember where I've seen it. VB COM objects that use STA and placed in
the Session object will, according to http://support.microsoft.com/default.aspx/kb/243548
and http://support.microsoft.com/default.aspx/kb/243543 , cause subsequent
requests for the object to be executed on the thread that placed the object
into the Session and therefore serialising them. I must have misread these
to imply that all ASP threads would be serialised, not just the ones for a
particular Session ID.

Dan
Aug 3 '06 #36

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:eC**************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 14:47:23 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:OT**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 14:02:34 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:Oh*************@TK2MSFTNGP06.phx.gbl...
Anthony wrote on Thu, 3 Aug 2006 11:35:44 +0100:

"Daniel Crichton" <ms****@worldofspack.comwrote in message
news:O2**************@TK2MSFTNGP02.phx.gbl...
Anthony wrote on Wed, 2 Aug 2006 17:07:39 +0100:
>
>"Daniel Crichton" <ms****@worldofspack.comwrote in message
>news:uK*************@TK2MSFTNGP06.phx.gbl.. .
>>Anthony wrote on Wed, 2 Aug 2006 15:44:44 +0100:
>>>
>>>"Michael D. Kersey" <md******@hal-pc.orgwrote in message
>>>news:e8**************@TK2MSFTNGP06.phx.gbl. ..
>>>>Anthony Jones wrote:
>>>>><%
>>>>>>
>>>>>Dim o: Set o = Server.CreateObject("MSXML2.DOMDocument.3.0")
>>>>>>
>>>>>Set Application("x") = o
>>>>>>
>>>>>%>
>>>>>
>>>>You failed to lock the Application object in your example,
which
>>>should
>>>>read:
>>>>
>>>What happens if you don't call Lock, Unlock?
>>>
>>Any other request can change the value of Application("x")
outside
of
>>>the
>>current ASP thread, effectively breaking the serialisation on the
initial
>>calls. Using Lock will prevent it being changed by another
request
>>>until
>the
>>Unlock method is called.
>>>
>>Dan
>>>
>Thanks for taking the time to answer my question. However I have
to
>be
>honest and admit I was being facetious.
>
After I'd posted my reply I did wonder, as you seemed to understand
from
replies in other branches that you know what Lock/Unlock does. I
didn't
>>>see
that a followup from me was needed though.
>
>Apart from the fact the that with or without a lock the code fails
>miserably anyway why does simply assigning a value to the
application
>>>>>object require a lock? With a lock anything that wants to change
it
>>>will,
>as soon as the lock is released, so why bother?
>
Because by assigning an apartment/single threaded object into it
you
>>>>force ASP into serialising all further page processing

Try my code. Add Lock/Unlock if you like. It doesn't work. The
application object will not store references to STA objects. Which
is
>the
point I was illustrating.

I've stored ADO apartment threaded objects in it before. I won't ever
do
>it
again. That was the first mistake I made on my first ASP application.

Nope it just looks that way. What you've been storing a free threaded
proxy to the ADO object.

OK, but that still, according to MS, will result in the ASP requests
being serialised, right?
If you mean that all requests to ASP will from now on go to the same
thread and have to queue one after the other then no. I'm not sure you
meant that though.

I felt sure years ago when I first started ASP development that MS had
published an article that said exactly this. However all I can find now
are
articles about how it will serialise only the specific Session, not the
Application, and cause ADO objects to remain memory resident (which was
the
other reason I very quickly changed my programming back then).
I think one problem is the use of word serialise. What you are describing
here is the affiliation of a session with a thread. This subsequently leads
to multiple requests for different sessions being serialised due having
become affiliated with the same work thread. There can other sets of
sessions affiliated with other threads but overall scalability of the
application is significantly impaired.

Requests for a single session are always serialised which is to say that ASP
only executes one request per session at a time. Subsequent requests for
the same session may run on different threads but not simultaneously. This
is because the Session object is single threaded.

The only time an entire application has all ASP requests serialised is when
it only has one worker thread or is in debug mode.
Looks like I've learnt something new again, but still reinforced the
recommendations I give to customers that putting ADO objects (and I tend
to
apply the same rule to all objects) in the Session/Application object is a
bad idea.

Dan


Aug 3 '06 #37
Max wrote:
<snipped>
Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences of
locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or critical
section) which would prevent multiple requests through the same process AND
use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance penalty of
a global lock. Any thoughts, experiences or that won't work because ...
would be appreciated.
Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?

If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw a
need and added these methods so ASP developers could use them. Avoiding
their use is suboptimal. Certainly the goal in your original post:
... to ensure that a
request for a particular ASP page is finalized before another request for
the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.
Aug 3 '06 #38

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
Max wrote:
<snipped>
Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences
of
locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
section) which would prevent multiple requests through the same process
AND
use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance penalty
of
a global lock. Any thoughts, experiences or that won't work because ...
would be appreciated.

Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?
It's not just Application.Lock that's involved here. For the duration of
the application lock nothing else can use the application lock not even a
simple read.

If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected as requests stall trying to read
the application object whilst it's locked by this operation.

>
If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw a
need and added these methods so ASP developers could use them.
Not for this job they didn't. Lock is there to avoid race conditions when
modifying multiple values.
Avoiding
their use is suboptimal. Certainly the goal in your original post:
... to ensure that a
request for a particular ASP page is finalized before another request
for
the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.
If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box. It isn't rocket science to
create a small COM wrapper round a mutex and now you have the right tool for
the job. Using Lock in this way is just setting yourself up for problems in
the future. (As is using debug mode or changing the worker thread count I
might add). All daft ideas. If you gonna do a job you might as well do it
right.

Aug 3 '06 #39
Max

"Anthony Jones" <An*@yadayadayada.comwrote in message
news:eD**************@TK2MSFTNGP06.phx.gbl...
>
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
>Max wrote:
<snipped>
Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences
of
locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
section) which would prevent multiple requests through the same process
AND
use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance
penalty
of
a global lock. Any thoughts, experiences or that won't work because
...
would be appreciated.

Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?

It's not just Application.Lock that's involved here. For the duration of
the application lock nothing else can use the application lock not even a
simple read.

If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected as requests stall trying to read
the application object whilst it's locked by this operation.

>>
If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw a
need and added these methods so ASP developers could use them.

Not for this job they didn't. Lock is there to avoid race conditions when
modifying multiple values.
>Avoiding
their use is suboptimal. Certainly the goal in your original post:
... to ensure that a
request for a particular ASP page is finalized before another request
for
the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.

If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box. It isn't rocket science to
create a small COM wrapper round a mutex and now you have the right tool
for
the job. Using Lock in this way is just setting yourself up for problems
in
the future. (As is using debug mode or changing the worker thread count I
might add). All daft ideas. If you gonna do a job you might as well do
it
right.
The COM object is very complex. It is single threaded and also maintains
state in the process between calls (using global variables and the like!)
and there are multiple calls to it from our customers web page. Yes I know
that is not how a good COM object is written but there is lots and lots of
legacy code in it!!). It cleans up on PageEnd so that the next request will
be treated correctly. Normally it would not run for a long time, however it
reads and executes byte code that is provided by our customers so "anything
may happen". It is however multiuser safe so that 2 or more processes do
not interfer with each other.

I was hoping that the idea to wrap it in a process lock would protect the
process state and to use a web garden would help with performance.
Aug 4 '06 #40
Anthony Jones wrote:
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
>Max wrote:
<snipped>
>>Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences
of
>>locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
>>section) which would prevent multiple requests through the same process
AND
>>use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance penalty
of
>>a global lock. Any thoughts, experiences or that won't work because ...
would be appreciated.
Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?

It's not just Application.Lock that's involved here. For the duration of
the application lock nothing else can use the application lock not even a
simple read.
A call to Application.Lock on an ASP page will not prevent another ASP
page (or another copy of the same ASP page) from reading data from the
Application object. In other words, Application.Lock locks out (other)
writers but not readers.
If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected
Yes. Primarily because requests for the ASP page(s) using the COM object
will be serialized for any critical code section.
as requests stall trying to read
the application object whilst it's locked by this operation.
No. They will be able to read data from the Application object unless
they call the Lock() method. Again, Application.Lock locks out (other)
writers but not readers.
>If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw a
need and added these methods so ASP developers could use them.

Not for this job they didn't. Lock is there to avoid race conditions when
modifying multiple values.
>Avoiding
their use is suboptimal. Certainly the goal in your original post:
>>... to ensure that a
request for a particular ASP page is finalized before another request
for
>>the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.

If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box.
Sure, but in this case we have a nail and we have a hammer. Why stop to
build your own hammer when a Microsoft hammer is provided?

Are we _afraid_ to use the big, bad Microsoft hammer? Maybe it will
_explode_ if we hit the nail! Maybe it is _radioactive_, will irradiate
the metal in the nail, the nail will fatigue prematurely and our house
will fall down! Maybe we'll die of radiation poisoning! Oooooooohhh! Who
knows _what_ _might_ _happen_!

Most scary of all, it might actually work! The Microsoft hammer may
strike the nail and drive it into the wood. Jeez!
It isn't rocket science to
create a small COM wrapper round a mutex and now you have the right tool for
the job.
Please feel free to post the code here for all to see. Please make sure
it's thoroughly debugged as is the Application.Lock/Unlock code I
provided earlier. I invite Max to compare running his application using
your to-be-provided code versus Application.Lock/Unlock.
Using Lock in this way is just setting yourself up for problems in
the future.
IMO this is making a mountain of a molehill. Max can test the
Application.Lock and .Unlock in 10 minutes easily; it's 2 lines of code.
Aug 4 '06 #41

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Anthony Jones wrote:
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
Max wrote:
<snipped>
Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences
of
>locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
>section) which would prevent multiple requests through the same
process
AND
>use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance
penalty
of
>a global lock. Any thoughts, experiences or that won't work because
....
>would be appreciated.
Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?
It's not just Application.Lock that's involved here. For the duration
of
the application lock nothing else can use the application lock not even
a
simple read.

A call to Application.Lock on an ASP page will not prevent another ASP
page (or another copy of the same ASP page) from reading data from the
Application object. In other words, Application.Lock locks out (other)
writers but not readers.
Ok do this test (I've done it and I know the results).

You'll need a small COM component to expose the Sleep API call, if not do
something else that doesn't hog the CPU but takes some time to complete.
(Like copying a large file across a network)
Page1.asp

Application("Thingy") = "Hello World"
Page2.asp

Application.Lock

MyComponent.Sleep 10000 ' 10 Seconds

Application.Unlock

Response.Write "Done"
Page3.asp

Response.Write Application("Thingy")

Hit Page1 to wake up the app and initialise Thingy.

Now using two separate instances of IExplorer (we need to simulate two
different sessions). Hit Page2.asp with one then immediately hit Page3.asp
with the other.

If you are correct Page3 should return immediately but of course it doesn't.
Page3 can't complete until Page2 releases the Lock. The lesson here is
don't believe everything you read in the documentation. Test it for
yourself.
If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected

Yes. Primarily because requests for the ASP page(s) using the COM object
will be serialized for any critical code section.
as requests stall trying to read
the application object whilst it's locked by this operation.

No. They will be able to read data from the Application object unless
they call the Lock() method. Again, Application.Lock locks out (other)
writers but not readers.
Do the test and see.
If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw
a
need and added these methods so ASP developers could use them.
Not for this job they didn't. Lock is there to avoid race conditions
when
modifying multiple values.
Avoiding
their use is suboptimal. Certainly the goal in your original post:
... to ensure that a
request for a particular ASP page is finalized before another request
for
>the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.
If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box.

Sure, but in this case we have a nail and we have a hammer. Why stop to
build your own hammer when a Microsoft hammer is provided?

Are we _afraid_ to use the big, bad Microsoft hammer? Maybe it will
_explode_ if we hit the nail! Maybe it is _radioactive_, will irradiate
the metal in the nail, the nail will fatigue prematurely and our house
will fall down! Maybe we'll die of radiation poisoning! Oooooooohhh! Who
knows _what_ _might_ _happen_!

Most scary of all, it might actually work! The Microsoft hammer may
strike the nail and drive it into the wood. Jeez!
Hmm... there can't be agreement here when you believe application.lock to
be something it is not. Did you understand my earlier statement 'Lock is
there to avoid race conditions'? Have you read my other posts in this
thread detailing when and why you need to use Lock?
It isn't rocket science to
create a small COM wrapper round a mutex and now you have the right tool
for
the job.

Please feel free to post the code here for all to see. Please make sure
it's thoroughly debugged as is the Application.Lock/Unlock code I
provided earlier. I invite Max to compare running his application using
your to-be-provided code versus Application.Lock/Unlock.
Fine. It's not like I've got anything better to do. Watch this space.
>
Using Lock in this way is just setting yourself up for problems in
the future.

IMO this is making a mountain of a molehill. Max can test the
Application.Lock and .Unlock in 10 minutes easily; it's 2 lines of code.
I'm sure it would work assessing its impact on the rest of the application
would be another matter. What affect it has in production isn't so easy.

Hmm.. and test it again when other changes are made to the applicaiton
because this code can affects the WHOLE application and again and again...

Aug 4 '06 #42

"Max" <ng*****@pfxcorp.comwrote in message
news:44***********************@per-qv1-newsreader-01.iinet.net.au...
>
"Anthony Jones" <An*@yadayadayada.comwrote in message
news:eD**************@TK2MSFTNGP06.phx.gbl...

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
Max wrote:
<snipped>
Thanks everyone for their answers.
I have been considering your suggestions and the possible
consequences
of
locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
section) which would prevent multiple requests through the same
process
AND
use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance
penalty
of
a global lock. Any thoughts, experiences or that won't work because
...
would be appreciated.

Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?
It's not just Application.Lock that's involved here. For the duration
of
the application lock nothing else can use the application lock not even
a
simple read.

If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected as requests stall trying to
read
the application object whilst it's locked by this operation.

>
If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw
a
need and added these methods so ASP developers could use them.
Not for this job they didn't. Lock is there to avoid race conditions
when
modifying multiple values.
Avoiding
their use is suboptimal. Certainly the goal in your original post:
... to ensure that a
request for a particular ASP page is finalized before another request
for
the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.
If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box. It isn't rocket science
to
create a small COM wrapper round a mutex and now you have the right tool
for
the job. Using Lock in this way is just setting yourself up for
problems
in
the future. (As is using debug mode or changing the worker thread count
I
might add). All daft ideas. If you gonna do a job you might as well do
it
right.
The COM object is very complex. It is single threaded and also maintains
state in the process between calls (using global variables and the like!)
and there are multiple calls to it from our customers web page. Yes I
know
that is not how a good COM object is written but there is lots and lots of
legacy code in it!!). It cleans up on PageEnd so that the next request
will
be treated correctly. Normally it would not run for a long time, however
it
reads and executes byte code that is provided by our customers so
"anything
may happen". It is however multiuser safe so that 2 or more processes do
not interfer with each other.

I was hoping that the idea to wrap it in a process lock would protect the
process state and to use a web garden would help with performance.
Ouch. Do you have other uses for the application object? If not then you
could use it as single mutex to protect the COM object as Michael suggested.
After all this misuse pales compared to the COM object you've described.

However since Michael continues to challange my POV I'll post some VB6 code
to wrap a Mutex when I get the chance.

Anthony.
Aug 4 '06 #43
>
However since Michael continues to challange my POV I'll post some VB6
code
to wrap a Mutex when I get the chance.
So here it is. Create a VB6 dll project called MutexFactory.
Set project properties Unattended Execution and Retain in Memory
Keep the Threading Model Apartment Threaded.

Add the following Mutex.cls Class Module set it's Instancing to
PublicNotCreatable.
Obviously you'll have undo the line wraps created by the reader.
Option Explicit
Private Const mcsModule = "Mutex."

Private Const ERROR_ALREADY_EXISTS = 183&
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Private Const LANG_NEUTRAL = &H0
Private Const WAIT_OBJECT_0 As Long = &H0
Private Const WAIT_TIMEOUT As Long = 258&
Private Const WAIT_ABANDONED As Long = &H80
Private Const WAIT_FAILED As Long = -1
Private Const HRESULT_WIN32 As Long = &H8007000
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA"
(lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As
String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long)
As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long)
As Long
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA"
(ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal
dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long,
Arguments As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle
As Long, ByVal dwMilliseconds As Long) As Long

Public Enum OwnershipState
TimedOut = 0
Succeeded
TakenAbandoned
End Enum

Private mhMutex As Long
Private mlOwnershipCnt As Long

Friend Sub Init(rsName As String)

mhMutex = CreateMutex(ByVal 0&, 0, rsName)

If mhMutex = 0 Then ApiRaise Err.LastDllError, mcsModule & "Init"

End Sub

Public Function GetOwnership(ByVal Timeout As Long) As OwnershipState

Dim lResult As Long

lResult = WaitForSingleObject(mhMutex, Timeout)

Select Case lResult
Case WAIT_FAILED
ApiRaise Err.LastDllError, mcsModule & "GetOwnership"
Case WAIT_OBJECT_0
mlOwnershipCnt = mlOwnershipCnt + 1
GetOwnership = Succeeded
Case WAIT_TIMEOUT
GetOwnership = TimedOut
Case WAIT_ABANDONED
mlOwnershipCnt = mlOwnershipCnt + 1
GetOwnership = TakenAbandoned
End Select

End Function

Public Function Release() As Boolean

Dim lResult As Long

lResult = ReleaseMutex(mhMutex)

If lResult <0 Then
mlOwnershipCnt = mlOwnershipCnt - 1
Else
ApiRaise Err.LastDllError, mcsModule & "Release"
End If

End Function

Private Sub Class_Terminate()

Dim i As Long

If mhMutex <0 Then

For i = 1 To mlOwnershipCnt
ReleaseMutex mhMutex
Next

CloseHandle mhMutex
mhMutex = 0

End If

End Sub

Public Sub ApiRaise(ByVal vlError As Long, rsSource As String)
Err.Raise vlError And &HFFFF& Or HRESULT_WIN32, rsSource, ApiError(vlError)
End Sub

Private Function ApiError(ByVal vlError As Long) As String

Dim s As String
Dim lCnt As Long

s = String(256, 0)

lCnt = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or
FORMAT_MESSAGE_IGNORE_INSERTS, _
ByVal 0&, vlError And &HFFFF&, LANG_NEUTRAL, s, Len(s),
ByVal 0&)

If lCnt <0 Then ApiError = Left$(s, lCnt)

End Function


Add other Class called Factory leave it's instancing set to Multiuse:-

Option Explicit
Private Declare Sub SleepApi Lib "kernel32" Alias "Sleep" (ByVal
dwMilliseconds As Long)

Public Function GetMutex(ByVal Name As String) As Mutex
Set GetMutex = New Mutex
GetMutex.Init Name
End Function

Public Sub Sleep(ByVal Milliseconds As Long)
SleepApi Milliseconds
End Sub
I've included the sleep method which helps with testing.

Compile this up.

Usage:

Create an instance of the Factory object ("MutexFactory.Factory")

oMF = Server.CreateObject("MutexFactory.Factory")
To get a mutex call the Factory GetMutex method with a unique name for the
resource you want to protect. The INSTANCE_META_PATH server variable can be
useful if there are multiple instances of your app on the server. Be
careful not to exceed MAX_PATH I recommend you don't make the string longer
than 255.

oMutex = oMF.GetMutex("Unique_Name")
To enter serialise a chunk of code you first need to take ownership of the
Mutex.
The GetOwnership method takes a timeout value in milliseconds. -1 is
indefinite (not recommended).

lResult = oMutex.GetOwnership(5000) ' Wait for 5 seconds to get ownership

0 = Timed out.
1 = Successfully acquired ownership of Mutex
2 = Aquired ownership of a Mutex that had been abandoned (the previously
owning thread terminated before releasing the mutex)

If ownership has been aquired the Mutex should be released as soon as is
possible.

oMutex.Release()

Multiple successful calls to GetOwnership should be matched by an equal
number of calls to Release.
Example:-

This page is serialises all calls to it without impacting any other pages
(apart from consuming worker threads that might otherwise be processing
other requests)

'Serialised.asp
<html>
<head>
<title>Serialised</title>
</head>
<body>
<%
Dim oMF: Set oMF = Server.CreateObject("MutexFactory.Factory")
Dim oMutex: Set oMutex = oMF.GetMutex(ScriptName)
Dim lOwnershipState

lOwnershipState = oMutex.GetOwnership(7000)

If lOwnershipState Then
Response.Write "Doing work<br />"
oMF.Sleep 5000
Response.Write "Finished"
oMutex.Release()
Else
Response.Write "Timeout trying to own mutex"
End If

Function ScriptName()
ScriptName = Request.ServerVariables("INSTANCE_META_PATH") &
Request.ServerVariables("SCRIPT_NAME")
End Function

%>
</body>
</html>

If the amount of work involved is significant it may be worth setting the
timeout low and responding back to the client asking them to try again later
(or if you can use a javascript solution to retry all the better). This
would avoid consuming threads if many requests want this resource on an
otherwise busy site.

I hope you find this useful.

Anthony.

Aug 4 '06 #44
Anthony Jones wrote:
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
>Max wrote:
<snipped>
>>Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences
of
>>locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
>>section) which would prevent multiple requests through the same process
AND
>>use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance
penalty
of
>>a global lock. Any thoughts, experiences or that won't work
because ...
>>would be appreciated.
Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?

It's not just Application.Lock that's involved here. For the duration of
the application lock nothing else can use the application lock not even a
simple read.
A call to Application.Lock on an ASP page will not prevent another ASP
page (or another copy of the same ASP page) from reading data from
OR WRITING DATA TO the Application object. In other words,
Application.Lock locks out only (other) pages that use Application.Lock.
If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected
Yes. Primarily because requests for the ASP page(s) using the COM object
will be serialized for any critical code section.
as requests stall trying to read
the application object whilst it's locked by this operation.
No. They will be able to read data from the Application object unless
they call the Lock() method. Again, Application.Lock locks out only
(other) pages that use Application.Lock.
>If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw a
need and added these methods so ASP developers could use them.

Not for this job they didn't. Lock is there to avoid race conditions
when
modifying multiple values.
>Avoiding
their use is suboptimal. Certainly the goal in your original post:
>>... to ensure that a
request for a particular ASP page is finalized before another request
for
>>the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.

If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box.
Sure, but in this case we have a nail and we have a hammer. Why stop to
build your own hammer when a Microsoft hammer is provided?

Most scary of all, it might actually work! The Microsoft hammer may
strike the nail and drive it into the wood. Jeez!
It isn't rocket science to
create a small COM wrapper round a mutex and now you have the right
tool for
the job.
Please feel free to post the code here for all to see. Please make sure
it's thoroughly debugged as is the Application.Lock/Unlock code I
provided earlier. I invite Max to compare running his application using
your to-be-provided code versus Application.Lock/Unlock.
Using Lock in this way is just setting yourself up for problems in
the future.
IMO this is making a mountain of a molehill. Max can test the
Application.Lock and .Unlock in 10 minutes easily; it's 2 lines of code.
Aug 4 '06 #45
Max
Thank you Anthony and Michael for your suggestions and code examples. I
have learnt quite a lot from all the replies to my posts. I will test you
suggestions and hopefully get the COM object functioning correctly.

Thanks again to everyone who reponded to my post.

Max

"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:ui***************@TK2MSFTNGP05.phx.gbl...
Anthony Jones wrote:
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:O3**************@TK2MSFTNGP04.phx.gbl...
Max wrote:
<snipped>
Thanks everyone for their answers.
I have been considering your suggestions and the possible consequences
of
>locking the whole application and would like your input on another
possibility coming out of Egbert's mutex solution.

If I were to wrap the COM object in a process lock (unname mutex or
critical
>section) which would prevent multiple requests through the same
process
AND
>use a web garden to allow multiple requests on the same page to use
different processes, I might be able to overcome the performance
penalty
of
>a global lock. Any thoughts, experiences or that won't work
because ...
>would be appreciated.
Perhaps there is undue concern about an imagined possible "performance
penalty".

1. Is your COM object a CPU hog?
2. Do your ASP pages already contain many calls to Application.Lock?
It's not just Application.Lock that's involved here. For the duration
of
the application lock nothing else can use the application lock not even
a
simple read.

A call to Application.Lock on an ASP page will not prevent another ASP
page (or another copy of the same ASP page) from reading data from
OR WRITING DATA TO the Application object. In other words,
Application.Lock locks out only (other) pages that use Application.Lock.
If the COM object performs an operation that requires any appreciable
elapsed time (regardless of whether the it's a CPU hog or not) then the
application can be significantly affected

Yes. Primarily because requests for the ASP page(s) using the COM object
will be serialized for any critical code section.
as requests stall trying to read
the application object whilst it's locked by this operation.

No. They will be able to read data from the Application object unless
they call the Lock() method. Again, Application.Lock locks out only
(other) pages that use Application.Lock.
If the answer to both questions is "yes", you _may_ _possibly_ incur
some performance penalty by using the Application object's Lock and
Unlock methods to cordon off your COM component.

If the answer to either question is "no", then I doubt you will see any
significant performance penalty.

Don't be afraid to try a ready, quick and easy solution. Microsoft saw
a
need and added these methods so ASP developers could use them.
Not for this job they didn't. Lock is there to avoid race conditions
when
modifying multiple values.
Avoiding
their use is suboptimal. Certainly the goal in your original post:
... to ensure that a
request for a particular ASP page is finalized before another request
for
>the page is processed
can be tested using these methods (we _are_ talking about two lines of
ASP code here). If they work, you're home free. If they fail, then
you've got another problem. If they work, but fail under load, then
you'll need to find another solution.
If all you have is a hammer everything looks like a nail. Many ASP
developers have more tools in their tool box.

Sure, but in this case we have a nail and we have a hammer. Why stop to
build your own hammer when a Microsoft hammer is provided?

Most scary of all, it might actually work! The Microsoft hammer may
strike the nail and drive it into the wood. Jeez!
It isn't rocket science to
create a small COM wrapper round a mutex and now you have the right
tool for
the job.

Please feel free to post the code here for all to see. Please make sure
it's thoroughly debugged as is the Application.Lock/Unlock code I
provided earlier. I invite Max to compare running his application using
your to-be-provided code versus Application.Lock/Unlock.
Using Lock in this way is just setting yourself up for problems in
the future.

IMO this is making a mountain of a molehill. Max can test the
Application.Lock and .Unlock in 10 minutes easily; it's 2 lines of code.

Aug 7 '06 #46
Anthony Jones wrote:
"Michael D. Kersey" <md******@hal-pc.orgwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
<snipped>
A call to Application.Lock on an ASP page will not prevent another ASP
page (or another copy of the same ASP page) from reading data from the
Application object. In other words, Application.Lock locks out (other)
writers but not readers.
I tried your suggested test (below). And what I said directly above is
totally, utterly wrong. As you stated when the Application.Lock method
is called, it locks out _all_ attempts to read or write from/to the
Application object by any page other than the caller.
Ok do this test (I've done it and I know the results).

You'll need a small COM component to expose the Sleep API call, if not do
something else that doesn't hog the CPU but takes some time to complete.
(Like copying a large file across a network)
Page1.asp
Application("Thingy") = "Hello World"

Page2.asp
Application.Lock
MyComponent.Sleep 10000 ' 10 Seconds
Application.Unlock
Response.Write "Done"

Page3.asp
Response.Write Application("Thingy")

Hit Page1 to wake up the app and initialise Thingy.

Now using two separate instances of IExplorer (we need to simulate two
different sessions). Hit Page2.asp with one then immediately hit Page3.asp
with the other.

If you are correct Page3 should return immediately but of course it doesn't.
Page3 can't complete until Page2 releases the Lock.
Yep!
The lesson here is
don't believe everything you read in the documentation.
While you've provide me a way to weasel out, upon reviewing the
documentation online, I believe I never understood it completely. The
Application.Lock documentation online states:

docThe Lock method blocks other clients from modifying the
docvariables stored in the Application object, ensuring that only
docone client at a time can alter or access the Application
doc^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docvariables.

And that "one client" is the client who has the Lock.

Thanks.

Aug 11 '06 #47
Anthony Jones suggested ASP test programs revealed that I had a critical
misunderstanding of the Application.Lock/Unlock methods:

Michael D. Kersey wrote:
Anthony Jones wrote:
<snipped>
AJ It's not just Application.Lock that's involved here.
AJ For the duration of the application lock nothing
AJ else can use the application lock not even a
AJ simple read.
>
MKA call to Application.Lock on an ASP page will not prevent another ASP
MKpage (or another copy of the same ASP page) from reading data from
MKOR WRITING DATA TO the Application object. In other words,
MKApplication.Lock locks out only (other) pages that use Application.Lock.

My statement directly above is wrong. As Anthony Jones correctly points
out, when the Application.Lock method is called, it locks out _all_
attempts to read or write from/to the Application object by any page
other than the caller.

<snipped>
AJ as requests stall trying to read
AJ the application object whilst it's locked by this operation.
>
MKNo. They will be able to read data from the Application object unless
MKthey call the Lock() method. Again, Application.Lock locks out only
MK(other) pages that use Application.Lock.

And my above statement is also wrong for the same reason.

<snipped>
Aug 12 '06 #48

This discussion thread is closed

Replies have been disabled for this discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.