2013-10-18 85 views
1

我正在開發的項目是一個客戶端 - 服務器應用程序,所有服務都以WCF和WPF中的客戶端編寫。有些情況下,服務器需要將信息推送給客戶端。我最初雖然關於使用WCF雙面打印服務,但在網上做了一些研究之後,我想很多人都在避免它,原因很多。在WCF中實現客戶端回調功能

接下來我想到的是讓客戶端創建主機連接,以便服務器可以使用它來向客戶端發起服務調用。然而,問題在於應用程序是通過互聯網部署的,因此這種方法需要配置防火牆以允許傳入流量,並且由於大多數用戶是常規用戶,這可能還需要配置路由器以允許端口轉發,這又是給用戶帶來麻煩。

我的第三個選擇是在客戶端生成一個後臺線程,它調用服務器上的GetNotifications()方法。然後,服務器端的這個方法阻塞,直到創建實際的通知,然後通知線程(使用AutoResetEvent對象可能?),並將信息發送給客戶端。我們的想法是這樣的:

客戶

private void InitializeListener() 
{ 
    Task.Factory.StartNew(() => 
    { 
     while (true) 
     { 
      var notification = server.GetNotifications(); 

      // Display the notification. 
     } 
    }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); 
} 

服務器

public NotificationObject GetNotifications() 
{ 
    while (true) 
    { 
     notificationEvent.WaitOne(); 
     return someNotificationObject; 
    } 
} 

private void NotificationCreated() 
{ 
    // Inform the client of this event. 
    notificationEvent.Set(); 
} 

在這種情況下,NotificationCreated()被調用時,服務器需要將信息發送到一個回調方法客戶。

您對這種方法有什麼看法?這是否可擴展?

回答

1

對於每個客戶端,您將在服務器上保持一個線程。如果你有幾百個客戶端,並且服務器無論如何都不會使用內存,那可能沒問題。如果可以有更多的客戶端,或者您不希望爲每個客戶端燒1MB堆棧,則應該進行一些更改:

  1. 使用異步WCF操作方法。它們允許您在方法等待時取消阻塞請求線程。
  2. 將事件模型更改爲異步一次。 SemaphoreSlim有異步支持。您也可以使用TaskCompletionSource

這樣你可以擴大到許多連接。

+0

感謝您的回答。客戶端使用的是.NET 4.0,因此目前無法支持'async'。你能詳細解釋第二個嗎?不確定你的意思是'將事件模型改爲異步一次.'。 – PoweredByOrange

+0

1:客戶端和服務器通過二進制網絡協議100%分離。一個可以使用異步,另一個可以做任何想要的事情,包括在C編程的手錶上運行或不使用異步。清楚了嗎? 2:如果你阻塞了服務器上的一個事件,那麼你正在阻塞一個線程(請參閱我的答案,瞭解它的含義)。所以你不想等事件發生。 'SemaphoreSlim.WaitOneAsync'允許你在邏輯上等待而不阻塞線程。研究一下它是如何工作的以及如何與WCF異步操作一起玩。 – usr

+0

會做一個研究。謝了哥們。 – PoweredByOrange