Csla.ApplicationContext and threads

Csla.ApplicationContext and threads

Old forum URL: forums.lhotka.net/forums/t/116.aspx


ajj3085 posted on Tuesday, May 16, 2006

Hi all,

It seems that ApplicationContext is only visible within the thread that created it. 
Any ideas on how to share context data across threads?

Thanks
Andy

Mark replied on Wednesday, May 24, 2006

I just ran across the need for this as well.  I've stored some configuration data in GlobalContext via the main application thread, but I'm also running a data access query on a background thread - which needs access to the configuration data as well. 

One solution that I think will work - modify ApplicationContext to use the AppDomain GetData / SetData methods (just on the client-side obviously).  Remote data portal will still need to use thread-local storage.

I'm working on a prototype now to see if it will work.  However, it'd be very nice if this (or something similar) were incorporated into the common CSLA code base (hint, hint).

ajj3085 replied on Wednesday, May 24, 2006

Mark,

Let me know how this works for you.  I was able to work around it (by taking the data i need and pushing it into an object to use as a 'parameter' for the thread.

I'd much rather have support for this built into the framework though.

Andy

Mark replied on Wednesday, May 24, 2006

Didn't take long at all to get working.  I'm attaching a modified copy of ApplicationContext (C# version) that uses AppDomain storage on the client and thread-local storage on the "server".  Just had to modify a couple of lines of code.  In my *very limited* testing, everything is working as expected.

Mark replied on Wednesday, May 24, 2006

Forgot to mention this - my quick workup is not thread-safe.  You'd need to code that in as well.  I didn't bother, since I mainly wanted to see if it worked first.  :-)

Here's hoping Rocky can incorporate a multi-threaded ApplicationContext object in CSLA.

ajj3085 replied on Thursday, May 25, 2006

Great,

I'll see how this works for me.

Maybe this could sneak into the 2.0.1 release? 

I've found that using threads is pretty much a must for WinForms application; well if yo don't want the application to stop responding when its fetching large amounts of data.  Using threads judiciously has made my application much more responsive and friendly to the users, and they appreciate that.  It doesn't look good when only half the window has repainted before your CPU spends its time fetching data.

Andy

RockfordLhotka replied on Thursday, May 25, 2006

This is a good thought. I don't know about making the whole object threadsafe though. Making it threadsafe would have a negative performance impact, even if you aren't using threads. Most people don't, and so they'd pay this cost for nothing.

I'd rather opt for the solution Microsoft uses pretty globally, which is to not be threadsafe, but rather provide a syncroot object you can use to implement your own locking.

Though that may not be realistic either, given that you might be making data portal calls on multiple threads. Of course (as I think about this), that is highly problematic, because the data portal just replaces the client data with the server data - so if you actually use/alter global context data on the server you'd lose some of that data in the case that multiple data portal calls occur at once.

Given that issue, it is clear that this requires quite a lot of thought - because the data portal might have to try and do some intelligent merge of data in globalcontext - and sitting here right now it isn't clear to me how such a thing would work - because that data is free-form, and so there's no guaranteed way for the data portal to match items to other items when doing a merge...

So it might be the case that globalcontext must be per-thread, while the User and ClientContext values can actually be client-wide.

Mark replied on Thursday, May 25, 2006

I see the dilemna with the GlobalContext object - if you were running locally, there wouldn't be an issue, but if you were using remoting, there is the chance for data to be overwritten. 

I don't see any difficulty with the ClientContext object, though, since it's not restored after a DataPortal call.  Store ClientContext in the app domain and all we need is a thread-safe way of getting/setting ClientContext and we should be good (I think). 

ajj3085 replied on Thursday, May 25, 2006

I think this approach would help me.

The data I'm sending back now through ApplicationContext could be returned by the Command object I have (now that I understand them better), and I could store the results in the ClientContext (since I don't really need to have the DataPortal code update this data once its set).

Andy


RockfordLhotka replied on Thursday, May 25, 2006

Right, I agree. I think that storing the ClientContext in the AppDomain should be fine, and leaving GlobalContext on the thread should avoid the merge issue.

The ClientContext is already a collection, and so has a SyncRoot property you can use for threadsafe access to its contents. I don't think I need to do anything there.

The ClientContext property itself is a different matter, and it needs to become threadsafe - meaning ClientContext, GetClientContext() and SetClientContext() all need to include locking code. I have put this into the code in cvs, and it passes the (updated) nunit tests. Whether I created any possible race conditions remains to be seen, but I don't think I did cause any such problems.

ajj3085 replied on Thursday, May 25, 2006

Wow,

This is great.  Thanks for adding it in so quickly!

Andy

ajj3085 replied on Friday, May 26, 2006

Just wanted to update;

I'm not using the 2.0.1 beta, and I put the data i need (a userid) in the ClientContext.

It works great, I no longer have to use my bad hack to keep things working across threads.

Thanks!

Copyright (c) Marimer LLC