Why are these asynchronous RIA Service calls executed in serial on the web server?

别来无恙 提交于 2019-12-22 19:37:31

问题


I'm calling the RIA Service method ImportSubcomponentFileSetFiles (which is an Invoke, not Query) twice as follows:

foreach (var viewModel in FileSetViewModels.Where(vm => vm.IsSelectedForImport))
{
    DomainContext.ImportSubcomponentFileSetFiles(viewModel.SubcomponentFileSet.Id, callback =>
                {
        //...
        DomainContext.Load(DomainContext.GetSubcomponentFileSetWithStatusQuery(subcomponentFileSetId), LoadBehavior.RefreshCurrent,
                            callback2 =>
        {
            //...
        }, true);
    }, null);
}

I can see in Fiddler that two requests go out to ImportSubcomponentFileSetFiles straight away.

ImportSubcomponentFileSetFiles takes ~15 seconds to complete. The first call comes back after about 15 seconds and the second call comes back 15 seconds after that. I can see from logging that the second call to ImportSubcomponentFileSetFiles doesn't start until the first call has completed.

My question is, why do these asynchronous requests get processed serially on the server and how can I process them in parallel?

ADDITIONAL INFORMATION

  • The WCF Ria Services are hosted in an ASP.NET web application.
  • I'm not storing anything in the session.
  • I'm using Entity Framework 4 in the service method.
  • The Domain Services class extends LinqToEntitiesDomainService<MyObjectContext>

My service method is as follows:

public void ImportSubcomponentFileSetFiles(int subcomponentId)
{
    Debug.WriteLine("{0}: {1} - ImportSubcomponentFileSetFiles method started", subcomponentId, DateTime.Now);

    //...code for fetching subcomponentFileSet

    subcomponentFileSet.ImportFiles(ObjectContext);

    Debug.WriteLine("{0}: {1} - ImportSubcomponentFileSetFiles method finished", subcomponentId, DateTime.Now);
}

Here are my logs detailing the second method call not starting until the first one has finished:

File Set A: 27/1/2011 11:20:06 PM 11:20:06 PM - Calling ImportSubcomponentFileSetFiles (Silverlight Client)
File Set A: 27/1/2011 11:20:06 PM 11:20:06 PM - ImportSubcomponentFileSetFiles Called (Silverlight Client)
File Set B: 27/1/2011 11:20:06 PM 11:20:06 PM - Calling ImportSubcomponentFileSetFiles (Silverlight Client)
File Set B: 27/1/2011 11:20:06 PM 11:20:06 PM - ImportSubcomponentFileSetFiles Called (Silverlight Client)
File Set A: 01/27/2011 23:20:06 - ImportSubcomponentFileSetFiles method started (Server)
File Set A: 01/27/2011 23:20:06 - ImportFiles Started (Server)
File Set A: 01/27/2011 23:20:23 - ImportFiles Finished (Server)
File Set A: 01/27/2011 23:20:23 - ImportSubcomponentFileSetFiles method finished (Server)
File Set A: 27/1/2011 11:20:23 PM - Import callback recieved (Silverlight Client)
File Set A: 01/27/2011 23:20:23 - GetSubcomponentFileSetWithStatus Started (Server)
File Set A: 01/27/2011 23:20:23 - GetSubcomponentFileSetWithStatus Finished (Server)
File Set B: 01/27/2011 23:20:23 - ImportSubcomponentFileSetFiles method started (Server)
File Set B: 01/27/2011 23:20:23 - ImportFiles Started (Server)
File Set A: 27/1/2011 11:20:23 PM - Refresh callback recieved (Silverlight Client)
File Set B: 01/27/2011 23:20:36 - ImportFiles Finished (Server)
File Set B: 01/27/2011 23:20:36 - ImportSubcomponentFileSetFiles method finished (Server)
File Set B: 27/1/2011 11:20:36 PM - Import callback recieved (Silverlight Client)
File Set B: 01/27/2011 23:20:36 - GetSubcomponentFileSetWithStatus Started (Server)
File Set B: 01/27/2011 23:20:36 - GetSubcomponentFileSetWithStatus Finished (Server)
File Set B: 27/1/2011 11:20:36 PM - Refresh callback recieved (Silverlight Client)

Cheers,
Chris


回答1:


I think that LinqToEntitiesDomainService derives from WCF classes, in which case, the following ServiceBehaviour properties might be set (either through code or config):

ServiceBehaviourAttribute.InstanceContextMode:

The default value, PerSession, instructs the service application to create a new service object when a new communication session is established between a client and the service application

ServiceBehaviourAttribute.ConcurrencyMode:

the default is Single.

Setting ConcurrencyMode to Single instructs the system to restrict instances of the service to one thread of execution at a time, which frees you from dealing with threading issues. A value of Multiple means that service objects can be executed by multiple threads at any one time. In this case, you must ensure thread safety.


This also led me to this statement:

If InstanceContextMode is set to PerSession and ConcurrencyMode is set to Single, each proxy gets its own service instance. All simultaneous calls from a single proxy to the service instance are serialized because only one thread is allowed into the service instance at one time. Because only one thread is allowed into the service at one time, all other calls made on the same proxy will block until that thread exits. If you have a large number of clients that are all making calls this causes a bottleneck.

So are you using a single proxy on your client, and could you create multiple ones, or is this something that is hidden from you in the silverlight client?




回答2:


You haven't mentioned the technology stack and/or code implementing your RIA services (ImportSubcomponentFileSetFiles) - from your fiddler trace, it clear that server side code is responsible for serial processing and you need to investigate there for the same.

For ASP.NET based services, the most probable cause could be use of Session State within service implementation. ASP.NET runtime guarantees that only one request can access Session State (in read/write mode) at a time (to simplify programming model).



来源:https://stackoverflow.com/questions/4813474/why-are-these-asynchronous-ria-service-calls-executed-in-serial-on-the-web-serve

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!