Print Page | Close Window

Is PersistenceManager thread-safe?

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce Classic
Forum Discription: For .NET 2.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=666
Printed Date: 11-Jun-2026 at 9:18am


Topic: Is PersistenceManager thread-safe?
Posted By: f3rland
Subject: Is PersistenceManager thread-safe?
Date Posted: 25-Jan-2008 at 7:04pm
We tried to remove entities from persistence manager in an event wich come from a thread and we get that error :
http://www.ideablade.com/forum/uploads/20080125_220048_error.txt - uploads/20080125_220048_error.txt
 
The error is not raised directly when our code is executed and seem to be from .NET Framework.
 
Here is the code in the event handler :
If IdeaBlade.Persistence.PersistenceManager.DefaultManager.DataSet.Tables.Contains("Model:SomeObject") Then
  IdeaBlade.Persistence.PersistenceManager.DefaultManager.RemoveEntities(GetType(Model.SomeObject), DataRowState.Unchanged)
End If
 
We cannot use the "Me.Invoke" in that context because the object is not a control.
 
Maybe there is another way to achieve the same task without that hack?
All we want to do is removing obsolete entities from cache to refetch them.
 
Or there is a way to force refresh for some objects base on filter or EntityQuery?
 
Thanks for your help!



Replies:
Posted By: davidklitzke
Date Posted: 26-Jan-2008 at 10:18am
The answer to your question is "No, the PersistenceManager is not thread-safe".
 

Please read this advice from our documentation:

The .NET Framework Class Library documentation for the DataSet class says this about its thread-safety: This type is safe for multithreaded read operations. You must synchronize any write operations. The same is true for the DevForce PersistenceManager. To make it thread-safe for write operations would require that we make thread-safe every method therein – and every method of the business objects it manages, including property setters. This would increase the PersistenceManagers complexity – and degrade its performance – significantly. Every user of the PersistenceManager, and every use thereof, would incur the performance penalty, whether such users and uses required thread-safety or not. At least 90% of the use cases that people submit to us for multi-threading involve retrieving data while other operations proceed. For this we have provided Asynchronous Queries. You call the PersistenceManagers GetEntitiesAsync() method, and we take care of putting the data retrieval operation on a separate thread so that the rest of your application can continue processing. Any number of such asynchronous queries can be launched simultaneously. You can read about asynchronous queries in the DevForce Developers Guide (in the chapter on Object Persistence), and see sample code in the Asynchronous Queries instructional unit that is shipped with the product. Does this mean that you cant do multi-threading (other than by using Asynchronous Queries) in a DevForce application? No, it does not. It just means that you should never share a single PersistenceManager, or any of the entities it manages in its cache, across multiple threads. Let us repeat:

 

o Never share a PersistenceManager across more than one thread.

 

o Never share entities from a given PersistenceManager in more than one thread.

 

Note that the problems that occur with multi-threaded applications are, by their very nature, timing-dependent and difficult to diagnose, reproduce, and test for. Your multi-threaded process can work successfully for long periods of time, then fail catastrophically when two or more inconsistent changes happen to be made simultaneously. You should definitely not count on this failure occurring at a convenient time!

 

4 Excerpted from Characterizing Thread Safety” by Brian Goetz, available on the web at:

http://www-128.ibm.com/developerworks/java/library/j-jtp09263.html

 

If your multi-threaded aspirations involve DevForce business objects:

 

Use a different PersistenceManager in each thread. Such PersistenceManagers can do anything a normal PersistenceManager can do; they can fetch (both synchronously and asynchronously), save, and so forth.

 

Never use PersistenceManager.DefaultManager when multi-threading – the DefaultManager is “global” to the AppDomain and will be shared among any threads in which it is used.

 

Never communicate entities across thread boundaries. If the caller must know about some entities, send a list of PrimaryKeys across the thread boundary in a call back. Alternatively, you could bury EntitySets in a call back to serialize copies of entities across the thread boundary.

 

If You’re Determined To Do Multi-Threading… Be sure you really need multiple threads. Remember, if all you want to do is fetch data asynchronously, you will be fully satisfied with Asynchronous Queries. Dont mess around with multi-threading if this is all you want to do. IdeaBlade DevForce Developers Guide Object Persistence IdeaBlade DevForce Q&A.doc Copyright © 2006, IdeaBlade, Inc, all rights reserved 56

Use caution when writing any multi-threaded app. Don't be lulled into a false sense of confidence just because it is easy to spawn a BackgroundWorker in .NET 2.0. Multi-threading is still hard. The BackgroundWorker made the syntax easy: it did not make good multi-threaded design easier! If youre new to multi-threaded programming, work with someone who has significant prior experience doing it, if at all possible. If you cant arrange that, do some serious reading and study on the topic before attempting it on a critical application. If your multi-threaded aspirations involve DevForce business objects:

 



Posted By: f3rland
Date Posted: 26-Jan-2008 at 11:13am
We don't have many choices.
One of our component sends us events through threads.
Those events tell us to refresh data for some tables.
And from that event we need to refresh entities in the persistence manager of the application (main thread).
 
I know we can work with lock and/or Mutex.
 


Posted By: davidklitzke
Date Posted: 26-Jan-2008 at 11:38am
Why can't you have your main thread process these events?
 
It is also OK if you have a separate Persistence Manger collect these inserted, modified, and deleted entities in its own cache, then have your main Persistence Manager import these entities.


Posted By: f3rland
Date Posted: 26-Jan-2008 at 11:49am
Events that came from our component are raised from a thread.
So another ExecutionContext...
 
Simplified example :
 
Class MainApplication
   Private mComponent as new SomeComponent
 
   Private Sub SomeEvent(byval SomeParam as SomeType) Handles mComponent.SomeEvent
      'Here we are in another context (thread) so we dont have access to main Persistence Manager.
      'We can see Shared PersistenceManager, modify it and access it but that raise exception as shown in first post.
      'And that's here we need to refresh PersistenceManager data.
   End Sub
End Class


Posted By: kimj
Date Posted: 26-Jan-2008 at 7:17pm
f3rland, take a look at the System.Threading.SynchronizationContext class.  You should be able to use it to Post or Send arguments back to your main thread.  Something like this:
 
    // "Main" thread
       // Create PM, etc.
   _synchronizationContext = System.Threading.SynchronizationContext.Current;
 
 
   private void SomeEventHandler(SomeType someParam ...) {
      object [] newArgs = new object[] {  someParam ... };
     _synchronizationContext.Post(ThreadSafeHandler, newArgs);
   }
 
  private void ThreadSafeHandler(args) {
    // can now safely use PM
  }
   
 


Posted By: f3rland
Date Posted: 29-Jan-2008 at 6:04am
Seem to work
Thank you Big%20smile



Print Page | Close Window