Making a base class' methods thread safe

S

Steve K.

I am creating several data access objects that all derive from a base class
which implements the web service access functionality.

For example (fake code):
<code>
public class DAOBase
{
protected List<TType> Search<TType>(string nameHint)
{
// code to login to web service session, execute search
// and return the result.
return new List<TType>();
}
}

public class CustomerDAO : DAOBase
{
public List<Customer> GetCustomer(string name)
{
return base.Search<Customer>(name);
}
}

public class OrderDAO : DAOBase
{
public List<Order> GetCustomerOrders(string name)
{
// some code that will execute a search using the DAOBase
// Search method
return null;
}
}
</code>

The web service access exposed in DAOBase is session based and I can only
have one session at a time. In other words, I can't run two searches at the
same time, they must be synchronous.
Once I've logged in (expensive operation) I want to reuse the same session
for all subsequent requests.

I'm thinking of the different ways that I can accomplish this. One idea is
to refactor my code so that my web service functionality is in a new
Singleton class, then the base class would have an instance of this
singleton. This way I could keep my session alive in the singleton and all
concrete objects would access the singleton through the base class.

This would give me thread safety, or, more accurately it won't prevent two
web service requests from being invoked on top of each other. If this
happens, the session will be killed. (bad)

I need to implement a queue to handle the web service request(s) from the
various concrete DAO classes, most likely using the command pattern and
wrapping all request in an object that can be enqueued.

So that is my first and only real idea to solve the issue. Another idea
that is fluttering around in my head is to keep the web service access in
the base class but make the methods static. This will give me the single
session shared with all concrete objects but introduces thread safety issues
(I think).

I would really like to hear what any of you think, before I start modifying
(and breaking) my code all over the place I thought I would ask first to see
if I'm on the right track.

Thanks for any input,
Steve
 
M

Marc Gravell

What is your server setup? You mention session, so I'm guessing it is
fairly simple (1 server?) [session doesn't scale "out" very well].. in
which case WCF will offer synchronization at the server for free.

Alternatively, WCF might also provide options at the client to perform
sync - in particular I'm thinking about custom behaviors and
listeners. I've used such to update a session token from the WCF
headers before, but it could just as easily be doing a Monitor.Enter/
Monitor.Exit on a static lock. However, in contrast - a WCF session is
very brittle - once it has errors (any fault) it should really be
destroyed; and "asmx" will suffer a similar fate if the server is
restarted. A better option may be to manage session *separately* to
the default session that WCF/asmx offer - perhaps a guid in a header
that the service can detect and read from a db [but which is islotated
from the comms stack].

Alterantively, you could use a form of factory / dependency injection
here... for instance, something like (where ILease<T> is just
IDisposable and offers the service via .Service):

using(ILease<MyService> svc = SomeFactory.GetLease<MyService>()) {
// do a batch of things with svc
svc.Service.Foo();
string wossit = svc.Service.Bar("Fred", "Wilma");
}

In this usage, you could obtain the lock during GetLease(), and free
the lock during Dispose(). But I'm assuming the above would use
separate proxies for each GetLease(), so again you would need separate
session management.

(this type of setup works fine with WCF, as it is fairly easy to write
a WCF factory and custom plugins to tweak what happens; much harder
for asmx)

Just some thoughts...
 
S

Steve K.

Hi Marc,

Comments inline>>>

Marc Gravell said:
What is your server setup? You mention session, so I'm guessing it is
fairly simple (1 server?) [session doesn't scale "out" very well].. in
which case WCF will offer synchronization at the server for free.

I'm not running the server, it's our "On Demand" web based ERP/CRM
application. I'm pretty sure they are running Oracle on linux, but could be
wrong.
Alternatively, WCF might also provide options at the client to perform
sync - in particular I'm thinking about custom behaviors and
listeners. I've used such to update a session token from the WCF
headers before, but it could just as easily be doing a Monitor.Enter/
Monitor.Exit on a static lock. However, in contrast - a WCF session is
very brittle - once it has errors (any fault) it should really be
destroyed; and "asmx" will suffer a similar fate if the server is
restarted. A better option may be to manage session *separately* to
the default session that WCF/asmx offer - perhaps a guid in a header
that the service can detect and read from a db [but which is islotated
from the comms stack].

This all sounds really cool, but I don't think it's an option for me (not my
server). I shoud have mentioned that in the original post, apologies.
Alterantively, you could use a form of factory / dependency injection
here... for instance, something like (where ILease<T> is just
IDisposable and offers the service via .Service):

using(ILease<MyService> svc = SomeFactory.GetLease<MyService>()) {
// do a batch of things with svc
svc.Service.Foo();
string wossit = svc.Service.Bar("Fred", "Wilma");
}

Interesting. You suggest the Factory to support multiple service objects?
In my case, I have only the one service I'm working with, so I don't think I
would need a factory.

In this usage, you could obtain the lock during GetLease(), and free
the lock during Dispose(). But I'm assuming the above would use
separate proxies for each GetLease(), so again you would need separate
session management.

(this type of setup works fine with WCF, as it is fairly easy to write
a WCF factory and custom plugins to tweak what happens; much harder
for asmx)

Just some thoughts...

I suspect I might have sent you in the wrong direction with my original
post. I'm interested in find a solution on the client side that will allow
me to share a single session between many objects.

I'm trying to think of another way to phrase it but can't really.
I will tinker around mocking up some pseudo code to illustrate what I'm
trying to do and post later.

Thanks for the reply and suggestions, I wish I was in control of the service
so I could explore your suggestions, they sound slick!
-Steve
 
M

Mufaka

Steve said:
The web service access exposed in DAOBase is session based and I can only
have one session at a time. In other words, I can't run two searches at the
same time, they must be synchronous.
Once I've logged in (expensive operation) I want to reuse the same session
for all subsequent requests.
I think your session should be expanded on a little bit. Is this a
clients logged in session? And if so, how is this maintained on the
client? ie: is it an open socket or is it a login token retrieved after
a successful login?

If it's something like the latter, I'd hope that the server wouldn't
limit you to synchronous calls against that session. That seems very
restrictive.

If you do have this restriction, a Singleton Queue with a callback
delegate will probably work.
 
S

sklett

Mufaka said:
I think your session should be expanded on a little bit. Is this a clients
logged in session? And if so, how is this maintained on the client? ie: is
it an open socket or is it a login token retrieved after a successful
login?

Hi Mufaka,

This is a client logged in session. The web service exposes a proxie which
represents the session to the web service. It's this service (which
contains the session) that I need to keep alive and reuse for multiple
objects. Sorry for the confusion.

If it's something like the latter, I'd hope that the server wouldn't limit
you to synchronous calls against that session. That seems very
restrictive.

It is very restrictive, the web service vendor is VERY concerned about the
web service traffic and I think that by limiting the users to synchronous
calls they are attempting to "encourage" developers to design efficient
solutions ;0)
If you do have this restriction, a Singleton Queue with a callback
delegate will probably work.

This is what I was thinking as well. The only question I have is if a
separate Singleton class is the way to go or if I should create the static
service functionality in the base class.
I'm going to do some experiments later.

Thanks for the suggestions and help,
Steve
 
M

Mufaka

sklett said:
Hi Mufaka,

This is a client logged in session. The web service exposes a proxie which
represents the session to the web service. It's this service (which
contains the session) that I need to keep alive and reuse for multiple
objects. Sorry for the confusion.



It is very restrictive, the web service vendor is VERY concerned about the
web service traffic and I think that by limiting the users to synchronous
calls they are attempting to "encourage" developers to design efficient
solutions ;0)


This is what I was thinking as well. The only question I have is if a
separate Singleton class is the way to go or if I should create the static
service functionality in the base class.
I'm going to do some experiments later.

Thanks for the suggestions and help,
Steve
Bleck :p

It's just a matter of preference I guess. My preference would be to
create a separate Singleton for testing and development purposes.

It also seems more natural to place this logic in a separate class
rather than having a base class manage the synchronous logic / session
state as well.

But, arguments can be made for the opposite as well.

Good luck with this. It's definitely an interesting problem to solve.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top