【问题标题】:How can I force unhandled exceptions in a WCF thread to crash the process?如何强制 WCF 线程中未处理的异常使进程崩溃?
【发布时间】:2010-10-06 13:29:13
【问题描述】:

所以这是场景:

我有一个 WCF 服务,它为每个操作定义了一堆 FaultContract。我想安排它,以便如果在与有效的 FaultContract 不匹配的 WCF 服务线程中引发未处理的异常,它会关闭整个进程而不仅仅是线程。 (原因是我想要一个包含异常信息的故障转储,因为它与合同不匹配。)

有什么办法可以干净利落地做到这一点吗?我遇到的主要问题是 WCF 想要将我的所有异常转换为客户端故障,以保持服务运行;我其实是想把整个过程搞下来,这实质上就是规避 WCF 的正常行为。

【问题讨论】:

    标签: c# wcf exception-handling crash-dumps


    【解决方案1】:

    Environment.FailFast() 将创建故障转储;它不会运行任何挂起的 try-finally 块,也不会运行任何终结器。

    【讨论】:

      【解决方案2】:

      您需要使用IErrorHandler 来自定义WCF 的错误处理行为。在调用 (ServiceHost).Open() 之前“应用行为”。

      例如(在 Main() 中查找显示“serviceHost.Description.Behaviors.Add(new FailBehavior());”的行):

      class FailBehavior : IServiceBehavior
      {
          public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
          {
              return;
          }
      
          public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
          {
              Console.WriteLine("The FailFast behavior has been applied.");
              var f = new FailOnError();
              foreach(ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers)
              {
                  chanDisp.ErrorHandlers.Add(f);      
              }
          }
      
          public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
          {
              return;
          }
      }
      
      class FailOnError : IErrorHandler
      {
          public bool HandleError(Exception error)
          {
              // this is called for every exception -- even ungraceful disconnects
              if( !(error is CommunicationException) )
                  throw new TargetInvocationException( "WCF operation failed.", error );
              else
                  throw new CommunicationException( "Unexpected communication problem. (see inner exception)", error );
      
              // Unreachable
              //return false; // other handlers should be called
          }
      
          public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
          {
              // Can't throw from here (it will be swallowed), and using Environment.FailFast
              // will result in all crashes going to the same WER bucket. We could create
              // another thread and throw on that, but instead I think throwing from HandleError
              // should work.
      
              //Console.WriteLine( "Unhandled exception: {0}", error );
              //Environment.FailFast("Unhandled exception thrown -- killing server");            
          }
      }
      
      class Program
      {
          static void Main( string[] args )
          {
              Console.WriteLine( "Greetings from the server." );
      
              Uri uri = new Uri( "net.tcp://localhost:5678/ServerThatShouldCrash" );
              using( ServiceHost serviceHost = new ServiceHost( typeof( Server ), uri ) )
              {
                  Binding binding = _CreateBinding();
      
                  serviceHost.AddServiceEndpoint( typeof( IServer ),
                                                  binding,
                                                  uri );
                  serviceHost.Description.Behaviors.Add(new FailBehavior());
                  serviceHost.Open();
      
                  // The service can now be accessed.
                  Console.WriteLine( "The service is ready." );
                  Console.WriteLine( "\nPress <ENTER> to terminate service.\n" );
                  Console.ReadLine();
              }
          }
      
          private static Binding _CreateBinding()
          {
              NetTcpBinding netTcp = new NetTcpBinding( SecurityMode.None );
              netTcp.ReceiveTimeout = TimeSpan.MaxValue;
              netTcp.ReliableSession.InactivityTimeout = TimeSpan.MaxValue;
              return netTcp;
          } // end _CreateBinding()
      }
      

      【讨论】:

        【解决方案3】:
        Application.Exit();
        

        可能会这样做,但用户会丢失他们当时正在处理的任何内容。

        【讨论】:

        • 不幸的是,它还有不产生故障转储的问题。
        猜你喜欢
        • 1970-01-01
        • 2019-01-27
        • 2014-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多