Почему эти асинхронные вызовы службы RIA выполняются последовательно на веб-сервере? - PullRequest
2 голосов
/ 27 января 2011

Я вызываю метод RIA Service 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.
  • Я ничего не храню в сессии.
  • Я использую Entity Framework 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)

Приветствия
Chris

Ответы [ 2 ]

3 голосов
/ 27 января 2011

Я думаю, что LinqToEntitiesDomainService является производным от классов WCF, и в этом случае могут быть установлены следующие свойства ServiceBehaviour (с помощью кода или конфигурации):

ServiceBehaviourAttribute.InstanceContextMode

Значение по умолчанию, PerSession, предписывает приложению службы создавать новый объект службы, когда между клиентом и приложением службы устанавливается новый сеанс связи

ServiceBehaviourAttribute.ConcurrencyMode

по умолчанию - Single.

Если для параметра ConcurrencyMode задано значение Single, система ограничивает количество экземпляров службы одним потоком выполнения за раз, что освобождает вас от проблем с многопоточностью. Значение Multiple означает, что служебные объекты могут выполняться несколькими потоками одновременно. В этом случае вы должны обеспечить безопасность потока.


Это также привело меня к этому утверждению :

Если для InstanceContextMode установлено значение PerSession, а для параметра ConcurrencyMode установлено значение Single, каждый прокси-сервер получает свой собственный экземпляр службы. Все одновременные вызовы с одного прокси-сервера на экземпляр службы сериализуются, поскольку в экземпляр службы одновременно может быть включен только один поток. Поскольку в службу допускается только один поток, все другие вызовы, сделанные на том же прокси-сервере, будут блокироваться до тех пор, пока этот поток не завершится. Если у вас большое количество клиентов, которые все звонят, это вызывает узкое место.

Так вы используете один прокси на своем клиенте и можете создать несколько прокси, или это что-то, что скрыто от вас в клиенте silverlight?

1 голос
/ 27 января 2011

Вы не упомянули технологический стек и / или код, реализующий ваши службы RIA (ImportSubcomponentFileSetFiles) - из вашей трассировки фиддлера ясно, что код на стороне сервера отвечает за последовательную обработку, и вам нужно исследовать ее на предмет того же ,

Для служб на базе ASP.NET наиболее вероятной причиной может быть использование состояния сеанса в реализации службы. Среда выполнения ASP.NET гарантирует, что только один запрос может одновременно обращаться к состоянию сеанса (в режиме чтения / записи) (для упрощения модели программирования).

...