2

我打电话RIA服务方法ImportSubcomponentFileSetFiles(这是一个调用,而不是查询)两次如下:这些异步RIA服务调用为什么在Web服务器上以串行方式执行?

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); 
} 

我可以小提琴手看到两个请求出去ImportSubcomponentFileSetFiles立竿见影。

ImportSubcomponentFileSetFiles需要约15秒钟才能完成。第一个电话在大约15秒后回来,第二个电话在15秒后回来。从日志记录中可以看到,第二次调用ImportSubcomponentFileSetFiles在第一次调用完成之前不会启动。

我的问题是,为什么这些异步请求在服务器上被串行处理,我该如何处理它们并行呢?

附加信息

  • 的WCF RIA服务托管在ASP.NET Web应用程序。
  • 我没有在会话中存储任何内容。
  • 我在服务方法中使用实体框架4。
  • 域服务类扩展LinqToEntitiesDomainService <MyObjectContext>

我的服务方法如下:

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); 
} 

这里是我的日志,详细介绍了第二个方法调用没有启动,直到第一个已完成:

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) 

干杯,
克里斯

回答

3

我认为LinqToEntitiesDomainService从WCF类派生,在这种情况下,下面的ServiceBehaviour属性可能设置(通过代码或配置):

ServiceBehaviourAttribute.InstanceContextMode

的默认值,PerSession,指示服务应用程序在客户端和服务应用程序之间建立新的通信会话时创建新的服务对象

ServiceBehaviourAttribute.ConcurrencyMode

默认值为Single。

将ConcurrencyMode设置为Single指示系统将服务的实例一次限制为一个执行线程,这使您无需处理线程问题。值为Multiple意味着服务对象可以在任何时候由多个线程执行。在这种情况下,您必须确保线程安全。


这也促使我this statement

如果InstanceContextMode设置为PerSession和ConcurrencyMode设置为Single,每个代理都有自己的服务实例。从单个代理到服务实例的所有同时呼叫都被序列化,因为一次只允许一个线程进入服务实例。因为一次只允许一个线程进入服务,所以在同一个代理上进行的所有其他调用将会阻塞,直到该线程退出。如果你有大量的客户都在打电话,这会造成瓶颈。

那么你在你的客户端上使用单一的代理,你可以创建多个,或者这是在Silverlight客户端隐藏的东西吗?

1

您没有提到的技术堆栈和/或代码实现您的RIA服务(ImportSubcomponentFileSetFiles) - 从你的提琴手跟踪,明确表示服务器端代码负责串行处理,你需要调查那里的相同。

对于基于ASP.NET的服务,最可能的原因可能是服务实现中使用会话状态。 ASP.NET运行时保证每次只有一个请求可以访问会话状态(以读/写模式)(以简化编程模型)。

+0

感谢您的反馈意见。我在上面提供了更多细节。 – Kip 2011-01-27 14:52:14