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