微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何处理WCF异常与代码合并的列表

如何解决如何处理WCF异常与代码合并的列表

|| 我正在尝试在SO上扩展此答案,以使WCF客户端在出现瞬态网络故障时重试,并处理其他需要重试的情况,例如身份验证到期。 题: 需要处理哪些WCF异常,正确的处理方式是什么? 除了[ѭ0]之外,我还是希望看到以下一些示例技术: 重试前延迟X秒 关闭并重新创建New()WCF客户端。处置旧的。 不要重试并重新抛出此错误 重试N次,然后抛出 由于不可能由一个人知道所有异常或解决异常的方法,因此请分享您所知道的。我将在下面的代码示例中汇总答案和方法
    // USAGE SAMPLE
    //int newOrderId = 0; // need a value for definite assignment
    //Service<IOrderService>.Use(orderService=>
    //{
    //  newOrderId = orderService.PlaceOrder(request);
    //}




    /// <summary>
    /// A safe WCF Proxy suitable when sessionmode=false
    /// </summary>
    /// <param name=\"codeBlock\"></param>
    public static void Use(UseServiceDelegateVoid<T> codeBlock)
    {
        IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
        bool success = false;
        try
        {
            codeBlock((T)proxy);
            proxy.Close();
            success = true;
        }
        catch (CommunicationObjectAbortedException e)
        {
                // Object should be discarded if this is reached.  
                // Debugging discovered the following exception here:
                // \"Connection can not be established because it has been aborted\" 
            throw e;
        }
        catch (CommunicationObjectFaultedException e)
        {
            throw e;
        }
        catch (MessageSecurityException e)
        {
            throw e;
        }
        catch (ChannelTerminatedException)
        {
            proxy.Abort(); // Possibly retry?
        }
        catch (ServerTooBusyException)
        {
            proxy.Abort(); // Possibly retry?
        }
        catch (EndpointNotFoundException)
        {
            proxy.Abort(); // Possibly retry?
        }
        catch (FaultException)
        {
            proxy.Abort();
        }
        catch (CommunicationException)
        {
            proxy.Abort();
        }
        catch (TimeoutException)
        {
         // Sample error found during debug: 

         // The message Could not be transferred within the allotted timeout of 
         //  00:01:00. There was no space available in the reliable channel\'s 
         //  transfer window. The time allotted to this operation may have been a 
         //  portion of a longer timeout.

            proxy.Abort();
        }
        catch (ObjectdisposedException )
        {
            //todo:  handle this duplex callback exception.  Occurs when client disappears.  
            // Source: https://stackoverflow.com/questions/1427926/detecting-client-death-in-wcf-duplex-contracts/1428238#1428238
        }
        finally
        {
            if (!success)
            {
                proxy.Abort();
            }
        }
    }
    

解决方法

编辑:多次关闭并重新打开客户端似乎有些效率低下。我在这里探索解决方案,如果找到了,将更新和扩展此代码。 (或者,如果David Khaykin发布了答案,我会将其标记为已接受) 经过几年的修改,下面的代码是我首选的处理WCF重试和处理异常的策略(在从Wayback机器上看到此博客发布之后)。 我调查了每个异常,以及该异常的处理方法,并注意到了一个共同特征。每个需要从通用基类继承的“重试”的异常。我还注意到,使客户端进入无效状态的每个permFail异常也来自共享基类。 下面的示例捕获客户端可以通过的每个WCF异常,并且可以针对您自己的自定义通道错误进行扩展。 WCF客户端使用示例 生成客户端代理后,就可以实现它。
Service<IOrderService>.Use(orderService=>
{
  orderService.PlaceOrder(request);
}
ServiceDelegate.cs 将此文件添加到您的解决方案。除非您要更改重试次数或要处理的异常,否则无需对此文件进行任何更改。
public delegate void UseServiceDelegate<T>(T proxy);

public static class Service<T>
{
    public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>(\"\"); 

    public static void Use(UseServiceDelegate<T> codeBlock)
    {
        IClientChannel proxy = null;
        bool success = false;


       Exception mostRecentEx = null;
       int millsecondsToSleep = 1000;

       for(int i=0; i<5; i++)  // Attempt a maximum of 5 times 
       {
           // Proxy cann\'t be reused
           proxy = (IClientChannel)_channelFactory.CreateChannel();

           try
           {
               codeBlock((T)proxy);
               proxy.Close();
               success = true; 
               break;
           }
           catch (FaultException customFaultEx)
           {
               mostRecentEx = customFaultEx;
               proxy.Abort();

               //  Custom resolution for this app-level exception
               Thread.Sleep(millsecondsToSleep * (i + 1)); 
           }

           // The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
           catch (ChannelTerminatedException cte)
           {
              mostRecentEx = cte;
               proxy.Abort();
               //  delay (backoff) and retry 
               Thread.Sleep(millsecondsToSleep  * (i + 1)); 
           }

           // The following is thrown when a remote endpoint could not be found or reached.  The endpoint may not be found or 
           // reachable because the remote endpoint is down,the remote endpoint is unreachable,or because the remote network is unreachable.
           catch (EndpointNotFoundException enfe)
           {
              mostRecentEx = enfe;
               proxy.Abort();
               //  delay (backoff) and retry 
               Thread.Sleep(millsecondsToSleep * (i + 1)); 
           }

           // The following exception that is thrown when a server is too busy to accept a message.
           catch (ServerTooBusyException stbe)
           {
              mostRecentEx = stbe;
               proxy.Abort();

               //  delay (backoff) and retry 
               Thread.Sleep(millsecondsToSleep * (i + 1)); 
           }
           catch (TimeoutException timeoutEx)
           {
               mostRecentEx = timeoutEx;
               proxy.Abort();

               //  delay (backoff) and retry 
               Thread.Sleep(millsecondsToSleep * (i + 1)); 
           } 
           catch (CommunicationException comException)
           {
               mostRecentEx = comException;
               proxy.Abort();

               //  delay (backoff) and retry 
               Thread.Sleep(millsecondsToSleep * (i + 1)); 
           }


           catch(Exception e)
           {
                // rethrow any other exception not defined here
                // You may want to define a custom Exception class to pass information such as failure count,and failure type
                proxy.Abort();
                throw e;  
           }
       }
       if (success == false && mostRecentEx != null) 
       { 
           proxy.Abort();
           throw new Exception(\"WCF call failed after 5 retries.\",mostRecentEx );
       }

    }
}
    ,我在Codeplex上启动了一个具有以下功能的项目 允许有效地重用客户端代理 清理所有资源,包括EventHandlers 在双工通道上运行 使用按通话服务 支持配置构造函数,或按工厂 http://smartwcfclient.codeplex.com/ 这是一项正在进行中的工作,受到了非常多的评论。如果有任何改进建议,我将不胜感激。 在实例模式下的用法示例:
 var reusableSW = new LC.Utils.WCF.ServiceWrapper<IProcessDataDuplex>(channelFactory);

 reusableSW.Reuse(client =>
                      {
                          client.CheckIn(count.ToString());
                      });


 reusableSW.Dispose();
    ,我们有一个WCF客户端,可以处理服务器上几乎所有类型的故障。渔获物清单很长,但不是必须的。如果仔细观察,您会发现许多异常是Exception类的子级定义(以及其他一些类)。 因此,您可以根据需要简化很多事情。也就是说,这是我们捕获的一些典型错误: 服务器超时 服务器太繁忙 服务器无法使用。     ,以下链接可能有助于处理WCF异常: http://www.codeproject.com/KB/WCF/WCFErrorHandling.aspx http://msdn.microsoft.com/en-us/library/cc949036.aspx     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。