New Posts New Posts RSS Feed: server side async query
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

server side async query

 Post Reply Post Reply
Author
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Topic: server side async query
    Posted: 10-Oct-2013 at 3:14am
Hi,

Since Devforce allow to asynchronous query the database from the client or the server, I want to use them on the server to optimize my work.

When you await a Task on the server you doesn't always come back to the original thread. When that happens the EntityManager throw an exception on the next query because it doesn't run on the original thread.
The solution is to set AuthorizedThreadId to null to allow to use the EntityManager from any thead but the documentation also say the EntityManager isn't thread safe.

So I am a bit confused with the "not thread safe" and the possibility to run the query on a different thread.

In which scenario (with AuthorizedThreadId = null) should I avoid using Async methods on the server ? 
Is running many query on the same EM in the same time (task.whenAll) while a few might be on a different thread is one of them ?
Is using the Async method on the server not recommended ?

Also, is using ConfigureAwait(false) on a query Silverlight not recommended ?

Regards,



Edited by kdev - 10-Oct-2013 at 4:40am
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 10-Oct-2013 at 10:24am
You can use async methods on the server.  The AuthorizedThreadId is used within some EntityManager calls in an awkward attempt to detect multi-threaded use of the EM.  In free threaded environments it's not expected that an async call will return to the original calling thread, and you can safely disable the check by setting AuthorizedThreadId to null.
 
Regarding use of ConfigureAwait(false) in Silverlight, this looks like a bug in the Async Targeting Pack.  DevForce uses version 1 of the "Async Targeting Pack for Visual Studio 11" to provide async support to Silverlight applications.  This pack has actually been deprecated in favor of the Microsoft.Bcl.Async package, but we haven't made this upgrade yet.
 
Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 11-Oct-2013 at 7:44am
thank you
Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 24-Oct-2013 at 9:23am
Originally posted by kimj

 DevForce uses version 1 of the "Async Targeting Pack for Visual Studio 11" to provide async support to Silverlight applications.  This pack has actually been deprecated in favor of the Microsoft.Bcl.Async package, but we haven't made this upgrade yet. 

Have you an ETA on the switch to Microsoft.Bcl.Async ? I'd like to benefits of the IProgress<T> which is, as far as I know,  only available on this package for SL.

regards


Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 24-Oct-2013 at 9:49am

I don't have an ETA but I can tell you that it won't be included in the upcoming 7.2.2 release. 

The new package adds several assemblies and is about 10x larger than the targeting pack, so we've been holding off on this until we saw a demand.  We'll see about including this in a release before year end.
Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 24-Oct-2013 at 9:59am
ok thanks for the info.


note : I just noticed that the IProgress<T> and Tuple<T1,T2..> implementation are not in the BCL Async package as I thought but in the BCL Portability pack.

Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 25-Oct-2013 at 8:12am
** Edited **

Hi,

I have a LOT of problems using async query methods on the server.
I get random exception or strange behavior while having 4 queries in // awaited in a Task.WhenAll.


so far I got in my main application those random Exception (can happen once every 10 or more exceutions) while awaiting Task.WhenAll() :
- "Execution of query against the server was successful but execution of query against the local cache failed"
- "Object reference not set to an instance of an object"
- another one about the collection changed during an enumeration

I also have a query returning 0 entity while it should ALWAYS return 1 entity (query part of the WhenAll).
If I execute the exact same query right after the WhenAll but withouth the Async method (standard ToList()), the query return the expected entity !!
As for the exception above, this is a random behavior.


I tried an exemple on NorthWindDB, here is the code (uploads/1623/ServerExecuteAsync.zip) :

    private static async void TestMothodWithAsync()
        {
            var em = new NorthwindIBEntities();
            em.AuthorizedThreadId = null;
            for (var bcl = 1; bcl <= 1000; bcl++)
            {
                em.Clear();
                Console.WriteLine("Iteration {0}", bcl);

                var tskOrder = new EntityQuery<Order>().With(em).ExecuteAsync();
                var tskRegion = new EntityQuery<Region>().With(em).ExecuteAsync();
                var tskCategory = new EntityQuery<Category>().With(em).ExecuteAsync();
                var tskTerritory = new EntityQuery<Territory>().With(em).ExecuteAsync();

                await Task.WhenAll(tskOrder, tskRegion, tskCategory, tskTerritory);
            }
        
            Console.WriteLine("Done.");
            Console.ReadLine();
        }

When I execute the console application, it will throw an Exception "Object reference not set to an instance of an object" on a random iteration (can be at iteration 1 or as late as at iteration 200).
Note : I didn't get the others kind of exception in the test project.


Am I doing something wrong ?

Below the trace of the Exception :

System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un objet.
   à IdeaBlade.EntityModel.EntityManager.<FireQueuedEvents>b__f9(Action a)
   à System.Collections.Generic.List`1.ForEach(Action`1 action)
   à IdeaBlade.EntityModel.EntityManager.FireQueuedEvents()
   à IdeaBlade.EntityModel.EntityManager.LoadingBlock.Dispose()
   à IdeaBlade.EntityModel.EntityQueryResultCollection..ctor(DataQueryResultCollection dqResults, EntityManager entityManager, MergeStrategy mergeStrategy)
   à IdeaBlade.EntityModel.EntityManager.MergeAndReturnUsingCache(IEntityFinder finder, DataQueryResultCollection dqResults)
   à IdeaBlade.EntityModel.EntityManager.ProcessFetchedData(DataQueryResultCollection dqResults, IEntityFinder finder)
   à IdeaBlade.EntityModel.EntityManager.<ExecuteFetchAsync>d__c1.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   à IdeaBlade.EntityModel.EntityQueryFinder.<ExecuteAsync>d__0.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   à IdeaBlade.EntityModel.EntityManager.<ExecuteQueryAsyncCore>d__69.MoveNext()
--- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
   à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   à System.Runtime.CompilerServices.TaskAwaiter.GetResult()





Edited by kdev - 25-Oct-2013 at 8:29am
Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 30-Oct-2013 at 4:26am
Hi,

any idea ?
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 30-Oct-2013 at 8:50am
Sorry, we're still looking at this and don't have a fix or workaround yet.
Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 30-Oct-2013 at 8:51am
ok thank you
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 30-Oct-2013 at 4:25pm
Although you can turn off the EntityManager's thread affinity by setting the AuthorizedThreadId to null, the problem in a free-threaded environment is that task continuations will also run on worker threads, and these threads can execute concurrently.   Internally in DevForce, when an async query completes a synchronous merge into the EM cache is performed, and it's here where you're seeing the problem, as these merges are all running concurrently on different threads.  The EM isn't designed to be thread safe, so eventually you will see these random exceptions.
 
To work around this behavior you can provide your own single-threaded SynchronizationContext, a working sample of which you can find at  http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx.  We use something like this within our test suite, which is also free threaded, when we need to ensure that async actions are synchronized to a thread.
Back to Top
kdev View Drop Down
Groupie
Groupie
Avatar

Joined: 03-Jan-2013
Posts: 83
Post Options Post Options   Quote kdev Quote  Post ReplyReply Direct Link To This Post Posted: 15-Nov-2013 at 7:37am
I tested it, it seems to works. Thanks.

Also about the microsoft BCL packages, since I have upgraded to SignalR v2 I have this warning on all my projets.

Warning 6 The predefined type 'System.Runtime.CompilerServices.IAsyncStateMachine' is defined in multiple assemblies in the global alias, using the definition of 'c:\Dev\Project\packages\Microsoft.CompilerServices.AsyncTargetingPack.1.0.0\lib\sl50\Microsoft.CompilerServices.AsyncTargetingPack.Silverlight5.dll' C:\Dev\Project\Harness\Global.Harness.SL\CSC Global.Harness.tn.SL

I m looking forward to the upgrade.

Regards


Edited by kdev - 15-Nov-2013 at 7:38am
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down