为什么这些异步 RIA 服务调用在 Web 服务器上串行执行?

发布于 2024-10-14 05:20:40 字数 3318 浏览 2 评论 0原文

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

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 应用程序中。
  • 我没有在会话中存储任何内容。
  • 我在服务方法中使用实体框架 4。
  • Domain Services 类扩展了 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)

干杯,
克里斯

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笛声青案梦长安 2024-10-21 05:20:40

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

ServiceBehaviourAttribute.InstanceContextMode

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

ServiceBehaviourAttribute.ConcurrencyMode

默认为单个。

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


这也导致我此声明

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

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

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?

°如果伤别离去 2024-10-21 05:20:40

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

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

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文