2011-05-26 80 views
1

我有一個作爲Windows服務運行的自託管的WCF服務。對於測試,我將它作爲控制檯應用程序運行。如何在未處理的錯誤時停止自託管的WCF服務?

我想捕獲服務中發生的所有未處理的異常並關閉主機。我希望捕獲產生響應時發生的所有非FaultException,但也捕獲所有在「空閒模式」下拋出的異常 - 即從某些工作線程拋出。

不幸的是,我無法通過IErrorHandler(未調用)或AppDomain.CurrentDomain.UnhandledException(未引發)來處理異常。

任何線索?

的App.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="TestServiceBahavior"> 
      <serviceMetadata httpGetEnabled="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service behaviorConfiguration="TestServiceBahavior" name="WcfErrorHandling.TestService"> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8001/TestService" /> 
      </baseAddresses> 
     </host> 
     <endpoint address="" binding="basicHttpBinding" 
      bindingConfiguration="" contract="WcfErrorHandling.ITestService" /> 
     <endpoint address="mex" binding="mexHttpBinding" 
      contract="IMetadataExchange" /> 
     </service> 
    </services> 
    </system.serviceModel> 
</configuration> 

代碼:

using System; 
using System.Linq; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Dispatcher; 

namespace WcfErrorHandling 
{ 
    [ServiceContract] 
    interface ITestService 
    { 
     [OperationContract] 
     string SayHello(string param); 
    } 

    public class TestService : ITestService 
    { 
     public string SayHello(string param) 
     { 
      if (param == "ae") 
       throw new ArgumentException("argument exception"); 
      if (param == "fe") 
       throw new FaultException("fault exception"); 
      return "hello"; 
     } 
    } 

    public class TestHost : ServiceHost, IErrorHandler 
    { 
     public TestHost() 
      : base(typeof(TestService)) 
     { 
     } 

     public void Start() 
     { 
      AppDomain.CurrentDomain.UnhandledException += 
       (sender, ea) => UnhandledExceptionHandler(ea.ExceptionObject as Exception); 

      Open(); 
      foreach (var channelDispatcher in ChannelDispatchers.OfType<ChannelDispatcher>()) 
       channelDispatcher.ErrorHandlers.Add(this); 
     } 

     public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
     { 
      // do nothing 
     } 

     public bool HandleError(Exception error) 
     { 
      if (!(error is FaultException)) 
       UnhandledExceptionHandler(error); 
      return true; 
     } 

     private void UnhandledExceptionHandler(Exception ex) 
     { 
      Close(); 
      Environment.Exit(1); 
     } 
    } 

    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var testHost = new TestHost(); 
      testHost.Start(); 
      Console.Out.WriteLine("Press any key to exit..."); 
      Console.ReadKey(); 
      testHost.Close(); 
     } 
    } 
} 

回答

0

有同樣的問題,這解決了這個問題對我來說:

讓你的服務實現此接口:

public class MyService : System.ServiceModel.Description.IServiceBehavior 

執行i t等這樣的:

public void AddBindingParameters(System.ServiceModel.Description.ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<System.ServiceModel.Description.ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
     return; 
    } 

    public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach (ChannelDispatcher channel in serviceHostBase.ChannelDispatchers) { channel.ErrorHandlers.Add(new ErrorHandler()); } 
    } 

    public void Validate(System.ServiceModel.Description.ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     return; 
    } 

並加入這個類:

public class ErrorHandler : IErrorHandler 
{ 
    bool IErrorHandler.HandleError(Exception error) 
    { return true; } 
    void IErrorHandler.ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault) 
    { return; } 
} 

現在設置一個斷點上的HandleError ..它會告訴你異常

+0

你的配置沒有被設置爲使用IErrorHandler你寫的。 @Flores正在指引你朝着正確的方向前進。看看這個[MSDN文章](http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx),看看如何正確配置它。 – 2011-06-09 12:34:26

+0

我使用這個沒有任何配置文件 – Flores 2011-06-09 13:10:35

+0

對不起,應該讓我的評論更清晰。 **問題**中顯示的配置未配置爲添加IErrorHandler行爲擴展,這就是爲什麼他的錯誤處理程序沒有被擊中。此答案中的示例服務代碼還實現了添加IErrorHandler實現的服務行爲,因此不需要配置文件條目。 – 2011-06-09 15:34:04