2015-06-24 32 views
2

我正在測試WCF併發性和實例化。對WCF服務的多個並行調用需要比單個調用更長的時間

有WCF服務:

public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     Thread.Sleep(1000); 
     return string.Format("You entered: {0}", value); 
    } 

} 

從我的形式應用我做調用此服務方法。當我打電話時,需要約1秒鐘。

private void single_Click(object sender, EventArgs e) 
    { 
     using (var service = new Service1Client()) 
     { 
      var sw = new Stopwatch(); 
      sw.Start(); 
      service.GetData(1); 
      sw.Stop(); 
      Debug.WriteLine(sw.Elapsed); 
     } 
    } 

但是當我用任務多次調用它時,它需要aprox:調用次數* 1秒。

private void mult_Click(object sender, EventArgs e) 
    { 
     using (var service = new Service1Client()) 
     { 
      var tasks = new List<Task<string>>(); 
      for (var i = 0; i < 5; i++) 
      { 

       int p = i; 
       tasks.Add(Task.Factory.StartNew(() => service.GetData(p))); 
      } 


      var sw = new Stopwatch(); 
      sw.Start(); 
      Task.WaitAll(tasks.ToArray()); 
      sw.Stop(); 
      Debug.WriteLine(sw.Elapsed); 

      foreach (var task in tasks) 
      { 
       Debug.WriteLine(task.Result); 
      } 


     } 
    } 

我嘗試實例化和併發(Instance mode = Per Call and Concurrency = Single等)的全部9個組合

有趣的事情是,如果我的所有工作創造新的ServiceClient對象,它工作正常,但我不認爲這是正確的做法。我覺得必須有一些我錯過的東西。如果是這樣,你能告訴我什麼?

回答

2

問題出在客戶端。

在對服務進行任何調用之前,您必須在Service1Client對象上明確呼叫Open()。否則,您的WCF客戶端代理將在內部致電EnsureOpened()。問題是,EnsureOpened()將導致每個請求等待,直到前一個請求在執行完成之前完成,這就是爲什麼一次只能發送一個請求,而不是按需要並行發送。

更改您這樣的代碼:

using (var service = new Service1Client()) 
{ 
    service.Open(); 
    // Do stuff... 
} 

文龍東的關於這個問題的優秀blog post

如果不先調用「打開」方法,代理會當在代理上進行第一次呼叫時在內部打開 。這稱爲 自動打開。爲什麼?當通過自動打開的 代理髮送第一條消息時,它將導致代理自動打開。您可以使用 .NET反射來打開方法 System.ServiceModel.Channels.ServiceChannel.Call,看看下面的代碼 :

if (!this.explicitlyOpened) 
    { 
     this.EnsureDisplayUI(); 
     this.EnsureOpened(rpc.TimeoutHelper.RemainingTime()); 
    } 

當你深入到EnsureOpened,你會看到,它調用 CallOnceManager .CallOnce。對於非第一次呼叫,您可以點擊 SyncWait.Wait等待第一個請求完成。這個 機制是確保所有請求等待代理被打開,並且它也確保正確的執行順序。因此,所有 請求都被序列化爲一個執行序列,直到所有 請求都從隊列中排出。在大多數情況下,這不是所需的 行爲。

+0

該死的你好:) – Dadroid

相關問題