保留這篇文章的目的,是有一種場景,就是,當你寫了一個Windows Service(單例,生存期長),你如何能很好的線上管理控制它,我所說的控制,不是簡單的‘開啟’、‘關閉’、‘暫停’、或者發送簡單的無參指令。而是有複雜互動的,用戶端傳送複雜參數,而Windows Serivce會傳回複雜的結果,例如:一個DataSet清單,或者一個對象集合等。
這種解決方案有很多,你可以使用傳統的IPC、郵槽、或者異步的MSMQ,或者WMI、Socket,但本文介紹的這種,是使用Remoting技術。
為了要達成目标,我們需要做的如下事情:
1、建立一個核心服務類(你的Windows Service主邏輯)
2、将伺服器端的單例服務,設定成永久生命期
3、Remoting建立單例服務端(可以使用任何宿主)
4、建立在Web用戶端,建立配置,調用服務端
因為是一個可行性測試,是以,越簡單越說,主要說明問題,及配置。接下來是實作。
1、建立一個核心服務類 代碼如下:
建立一個類庫項目,取名為:ClassLibrary.Test
在其中建立兩個類
核心主類Exchange
Public Class Exchange
Inherits System.MarshalByRefObject
Private mNextIndex As Integer Public Sub New()
Console.WriteLine("Exchange Started")
mNextIndex = 100
End Sub Public Function NextOrder() As Order
mNextIndex += 1
Console.WriteLine("Exchange NextOrder:" & mNextindex)
Return New Order(mNextIndex)
End Function Public Overrides Function InitializeLifetimeService() As Object
'Return MyBase.InitializeLifetimeService()
Console.WriteLine("Never Lifetime")
Return Nothing '不傳回,表示無限期的生命周期
End Function
End Class
還有一個實體類Order
<Serializable()> Public Class Order
Private mIndex As Integer Public Sub New(ByVal index As Integer)
Console.WriteLine("Order:New:" & index)
mIndex = index End Sub
Public ReadOnly Property Index() As Integer
Get
Console.WriteLine("Order:Index:" & mIndex)
Return mIndex
End Get
End Property
End Class
2、将伺服器端的單例服務,設定成永久生命期
就是上面代碼的下列部分,直接傳回Nothing,就是無限期生命周期
Public Overrides Function InitializeLifetimeService() As Object
'Return MyBase.InitializeLifetimeService()
Console.WriteLine("Never Lifetime")
Return Nothing '不傳回,表示無限期的生命周期
End Function
3、Remoting建立單例服務端(可以使用任何宿主)
1)建立一個項目,在配置檔案app.config中加入如下資訊:
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="Singleton"
type="ClassLibrary.Test.Exchange, ClassLibrary.Test"
objectUri="Exchange" />
</service>
<channels>
<channel port="10001" ref="tcp"/>
</channels>
</application>
</system.runtime.remoting>
2)在代碼中調用:
RemotingConfiguration.Configure("Dormice.App.Client.Test.exe.config", False)
<system.runtime.remoting>
<application>
<client>
<wellknown type="ClassLibrary.Test.Exchange, ClassLibrary.Test" url="tcp://localhost:10001/Exchange"/>
</client>
<channels>
<channel ref="tcp" useDefaultCredentials="true"/>
</channels>
</application>
</system.runtime.remoting>
'Create proxy to remote object
Dim url As String = "tcp://localhost:10001/Exchange"
Dim exchange As Exchange = Activator.GetObject(GetType(Exchange), url) 'Call remote function
Dim order As Order = exchange.NextOrder()
'Console.WriteLine("Client:NextOrder returned:" & order.Index)
Me.lblOrderIndex.Text = order.Index