我在VS 2010中有一個解決方案:一個WCF服務庫項目(「NotifyService」)和兩個Windows Forms項目,一個用於服務器(「NotifyServer」),另一個用於客戶端(「NotifyClient」)。我的目標是擁有一個雙工WCF服務,當服務器推出通知時,它將通知任何數量的連接客戶端。除了訂閱和取消訂閱服務器的更新外,客戶端不需要與服務器通信。然而,我似乎遇到了困擾InstanceContext的問題。分離出一個wcf服務,服務器和客戶端
下面是WCF服務的代碼:
<ServiceContract(
CallbackContract:=GetType(INotifyCallback),
SessionMode:=SessionMode.Required)>
Public Interface INotifyService
<OperationContract()>
Sub Notify(ByVal what As String)
<OperationContract()>
Sub Subscribe()
<OperationContract()>
Sub Unsubscribe()
End Interface
Public Interface INotifyCallback
<OperationContract(IsOneWay:=True)>
Sub OnNotify(ByVal what As String)
End Interface
<ServiceBehavior(
ConcurrencyMode:=ConcurrencyMode.Single,
InstanceContextMode:=InstanceContextMode.PerCall)>
Public Class NotifyService
Implements INotifyService
Private _callbacks As New List(Of INotifyCallback)
Public Sub Notify(ByVal what As String) Implements INotifyService.Notify
For Each callback As INotifyCallback In _callbacks
callback.OnNotify(what)
Next
End Sub
Public Sub Subscribe() Implements INotifyService.Subscribe
Dim client As INotifyCallback = OperationContext.Current.GetCallbackChannel(Of INotifyCallback)()
If Not _callbacks.Contains(client) Then
_callbacks.Add(client)
End If
End Sub
Public Sub Unsubscribe() Implements INotifyService.Unsubscribe
Dim client As INotifyCallback = OperationContext.Current.GetCallbackChannel(Of INotifyCallback)()
If _callbacks.Contains(client) Then
_callbacks.Remove(client)
End If
End Sub
End Class
服務器表格必須由服務庫和自主機上創建的DLL的引用代碼的WCF的服務器實例:
Public Class frmServer
Private _host As ServiceHost
Private _notifier As NotifyService.NotifyService
Public Sub go() Handles Me.Load
_host = New ServiceHost(GetType(NotifyService.NotifyService), New Uri("net.tcp://localhost:10000"))
_host.AddServiceEndpoint(GetType(NotifyService.INotifyService), New NetTcpBinding, "NotifyService")
_host.Description.Behaviors.Add(New ServiceMetadataBehavior)
_host.AddServiceEndpoint(GetType(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding, "mex")
_host.Open()
_notifier = New NotifyService.NotifyService
End Sub
Private Sub send() Handles Button1.Click
_notifier.Notify("Foo")
End Sub
End Class
大部分似乎都工作。我可以使用WcfTestClient進行連接,它至少可以看到服務,但由於它是一個啓用了雙工的net.tcp綁定,我實際上無法使用該客戶端對其進行測試。
當我創建客戶端時,我添加了名爲NotifyGateway的服務引用。這裏的客戶表單代碼:
<CallbackBehavior(
ConcurrencyMode:=ConcurrencyMode.Single,
UseSynchronizationContext:=False)>
Public Class frmClient
Implements NotifyGateway.INotifyServiceCallback
Private _service As NotifyGateway.NotifyServiceClient = Nothing
Public Sub OnNotify(ByVal what As String) Implements NotifyGateway.INotifyServiceCallback.OnNotify
MsgBox(what)
End Sub
Public Sub go() Handles Button1.Click
_service = New NotifyGateway.NotifyServiceClient(New InstanceContext(Me), New NetTcpBinding, New EndpointAddress("net.tcp://localhost:10000/NotifyService"))
_service.Open()
_service.Subscribe()
End Sub
End Class
由於我通過代碼設置了一切,所以沒有app.config文件。我遇到的問題是我的訂閱方法從未被調用過。在調試時,在遍歷該行(但不是例外)後出現錯誤,提示「無法自動進入服務器,調試器未能在服務器進程中停止」。當我回到我的服務器表單並單擊旨在在回調客戶端上引發事件的按鈕時,它會進入NotifyService類,但_callbacks
列表爲空,這表示Subscribe方法從未運行過,或者它從未在該實例上運行過。
我已經打了近一個星期。這幾乎是一個完全相同的副本,至少在服務方面,與here描述的內容相同,並且我已經編譯並且它可以工作。所以我有點失落,因爲我要去哪裏錯...
子彈點2做到了。由於我自己缺乏對C#到VB的轉換的關注。這不會太有用 - 只有極少數的計算機,最多,並在同一網絡上,所以(不要畏縮)我不擔心線程安全。共享成員將工作得很好。謝謝! – mounty
然後我會用'InstanceContextMode.Single' /'ConcurrencyMode.Single'。如果你同時得到多個請求,這隻會減慢速度,那就是你將遇到併發問題。 –