【问题标题】:Why are these asynchronous RIA Service calls executed in serial on the web server?为什么这些异步 RIA 服务调用会在 Web 服务器上串行执行?
【发布时间】:2011-01-27 23:45:15
【问题描述】:

我正在调用 RIA 服务方法 ImportSubcomponentFileSetFiles(这是一个 Invoke,而不是 Query)两次,如下所示:

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

我可以在 Fiddler 中看到两个请求立即发送到 ImportSubcomponentFileSetFiles

ImportSubcomponentFileSetFiles 大约需要 15 秒才能完成。第一个电话在大约 15 秒后返回,第二个电话在 15 秒后返回。我可以从日志中看到,对 ImportSubcomponentFileSetFiles 的第二次调用在第一次调用完成之前不会开始。

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

其他信息

  • WCF Ria 服务托管在 ASP.NET Web 应用程序中。
  • 我没有在会话中存储任何内容。
  • 我在服务方法中使用了 Entity Framework 4。
  • 域服务类扩展了 LinqToEntitiesDomainService

我的服务方式如下:

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)

干杯,
克里斯

【问题讨论】:

    标签: c# silverlight asynchronous entity-framework-4 wcf-ria-services


    【解决方案1】:

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

    ServiceBehaviourAttribute.InstanceContextMode:

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

    ServiceBehaviourAttribute.ConcurrencyMode:

    默认为单一。

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


    这也把我带到了this statement

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

    那么您是在客户端上使用单个代理吗,您可以创建多个代理,还是在 silverlight 客户端中对您隐藏的东西?

    【讨论】:

      【解决方案2】:

      您没有提到实现 RIA 服务的技术堆栈和/或代码 (ImportSubcomponentFileSetFiles) - 从您的提琴手跟踪中,很明显服务器端代码负责串行处理,您需要在那里进行调查.

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

      【讨论】:

      • 感谢您的反馈。我在上面提供了更多详细信息。
      • @da_ponc,请参阅@Damien 的回复 - 如果您没有配置任何内容,那么默认值可能会序列化您的调用!如果您不依赖会话行为,请将InstanceContextMode 更改为PerCallSessionMode 更改为Not Allowed。查看这篇文章了解更多信息:msdn.microsoft.com/en-us/library/ms731193.aspx
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-24
      • 2023-03-15
      相关资源
      最近更新 更多