簡體   English   中英

在WCF Web服務內部署WCF Windows服務客戶端

[英]Disposing a WCF windows service client inside a WCF web service

我有一個WCF Web服務,可以訪問另一台計算機上的WCF Windows服務。 Windows服務執行所有數據訪問,並將結果傳遞給Web服務。 我已經閱讀了幾篇有關正確配置WCF服務的服務客戶端的文章,但是我不確定在Web服務中執行此操作的最佳方法是什么。 (如果有幫助,則Web服務是PerCall而不是PerSession)

這就是我現在正在做的所有事情:

 Public Class Service1
  Implements IService1

  Private p_oWindowsService As DataService.Service1Client

  Public Sub New()
    p_oWindowsService = New DataService.Service1Client
  End Sub

  Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData
    Return p_oWindowsService.GetData(value)
  End Function

  Public Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType Implements IService1.GetDataUsingDataContract
    If composite Is Nothing Then
      Throw New ArgumentNullException("composite")
    End If
    If composite.BoolValue Then
      composite.StringValue &= "Suffix"
    End If
    Return composite
  End Function

從我所讀的內容來看,這是一個主要問題,我現在根本不會部署服務客戶端。 我正在尋找的解決方法是在GetData函數內類似這樣的內容:

 Public Function GetData(ByVal value As Integer) As String Implements IService1.GetData
     Using oWindowsService As New DataService.Service1Client
        Return oWindowsService.GetData(value)
     End Using        
  End Function

基於WCF客戶端“使用”塊問題的最佳解決方法是什么? ,我知道我實際上不應該依賴using塊。 但是我應該在每個功能中創建並部署服務客戶端嗎? 那是我真正的問題。

謝謝。

是的,不要使用處置。 像這樣做:

var client = new ...;
try {
   // Do work

   // Everything went well so close the client
   client.Close();
}
catch( Exception ex ) {
   // Something went wrong so call abort
   client.Abort();

   // Other logging code 
}

if( client.State != System.ServiceModel.CommunicationState.Closed ) {
   client.Close();
}

在客戶端上調用Close()會通知服務實例該服務實例不再使用,並且可能由GC收集(取決於服務實例管理)。

您可能想知道為什么在catchAbort 原因是:

給定WCF綁定使用傳輸會話,出現故障后客戶端甚至無法關閉它(如果沒有傳輸層會話,則客戶端可以使用或關閉代理,但是不建議這樣做,因為會話的配置可以更改)。 因此,在發生故障之后,唯一安全的操作是中止代理。

更多關於Abort VS Close


編輯

在您的評論中,您詢問:

您是否建議在Web服務調用Windows服務的每個函數中創建和關閉這樣的服務客戶端?

不,我認為沒有必要。 讓我們看看您正在從Web應用程序(ASP MVC)調用WCF服務,然后您將在控制器的Dispose方法中執行類似的操作,因為ClientBase<TChannel>實現了ICommunicationObject

protected override void Dispose(bool disposing) {
     base.Dispose( disposing );

     ServiceHelper.DisposeService( ( this._whateverServiceClient as ICommunicationObject ) );
 }

這是可以在任何地方使用的ServiceHelper類:

public static class ServiceHelper {

  /// <summary>
  /// Disposes the given service.
  /// </summary>
  /// <param name="service">The service.</param>
  public static void DisposeService(ICommunicationObject service) {

     if( service != null ) {

        bool abort = true;

        try {
           if( service.State == CommunicationState.Opened || service.State == CommunicationState.Opening ) {
              service.Close();
              abort = false;
           }
        }
        finally {

           // Determine if we need to Abort the communication object.
           if( abort )
              service.Abort();
        }
     }
  }

}

如果您是從另一個客戶端調用的,則想法將是相同的。

您不需要顯式處置客戶端,如果真的需要,那么這是正確關閉並處置客戶端的一種方法:

        // use client
        try
        {
            ((IClientChannel)client).Close();
        }
        catch
        {
            ((IClientChannel)client).Abort();
        }
        finally
        {
            ((IDisposable)client).Dispose();
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM