zoukankan      html  css  js  c++  java
  • Wcf Client 异常和关闭的通用处理方法

    在项目中采用wcf通讯,客户端很多地方调用服务,需要统一的处理超时和通讯异常以及关闭连接。

    1.调用尝试和异常捕获

    首先,项目中添加一个通用类ServiceDelegate.cs

     1 public delegate void UseServiceDelegate<T>(T proxy);
     2 
     3 public static class Service<T>
     4 {
     5     public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>(""); 
     6 
     7     public static void Use(UseServiceDelegate<T> codeBlock)
     8     {
     9         T proxy = _channelFactory.CreateChannel();
    10         bool success = false;
    11 
    12 
    13        Exception mostRecentEx = null;
    14        for(int i=0; i<5; i++)  // Attempt a maximum of 5 times 
    15        {
    16            try
    17            {
    18                codeBlock(proxy);
    19                proxy.Close();
    20                success = true;
    21                break;
    22            }
    23 
    24            // The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
    25            catch (ChannelTerminatedException cte)
    26            {
    27               mostRecentEx = cte;
    28                proxy.Abort();
    29                //  delay (backoff) and retry 
    30                Thread.Sleep(1000 * (i + 1)); 
    31            }
    32 
    33            // The following is thrown when a remote endpoint could not be found or reached.  The endpoint may not be found or 
    34            // reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
    35            catch (EndpointNotFoundException enfe)
    36            {
    37               mostRecentEx = enfe;
    38                proxy.Abort();
    39                //  delay (backoff) and retry 
    40                Thread.Sleep(1000 * (i + 1)); 
    41            }
    42 
    43            // The following exception that is thrown when a server is too busy to accept a message.
    44            catch (ServerTooBusyException stbe)
    45            {
    46               mostRecentEx = stbe;
    47                proxy.Abort();
    48 
    49                //  delay (backoff) and retry 
    50                Thread.Sleep(1000 * (i + 1)); 
    51            }
    52 
    53            catch(Exception  )
    54            {
    55                 // rethrow any other exception not defined here
    56                 // You may want to define a custom Exception class to pass information such as failure count, and failure type
    57                 proxy.Abort();
    58                 throw ;
    59            }
    60        }
    61        if (mostRecentEx != null) 
    62        { 
    63            proxy.Abort();
    64            throw new Exception("WCF call failed after 5 retries.", mostRecentEx );
    65        }
    66 
    67     }
    68 }
    View Code

    然后,这样调用:

    无返回值:

    Service<IOrderService>.Use(orderService=>
    {
      orderService
    .PlaceOrder(request);
    }

    有返回值:

    int newOrderId = 0; // need a value for definite assignment
    Service<IOrderService>.Use(orderService=>
      {
        newOrderId = orderService.PlaceOrder(request);
      });
    Console.WriteLine(newOrderId); // should be updated

    2.使用Using方式确保关闭

    在客户端扩展一个wcf client的部分类,重写Dispose方法,代码如下:

     1 namespace 命名空间要和生成的代码里一致
     2 {
     3     /// <summary>
     4     ///     ExtDataClient
     5     /// </summary>
     6     public partial class *****Client : IDisposable
     7     {
     8         #region IDisposable implementation
     9 
    10         /// <summary>
    11         ///     IDisposable.Dispose implementation, calls Dispose(true).
    12         /// </summary>
    13         void IDisposable.Dispose()
    14         {
    15             Dispose(true);
    16         }
    17 
    18         /// <summary>
    19         ///     Dispose worker method. Handles graceful shutdown of the
    20         ///     client even if it is an faulted state.
    21         /// </summary>
    22         /// <param name="disposing">
    23         ///     Are we disposing (alternative
    24         ///     is to be finalizing)
    25         /// </param>
    26         protected virtual void Dispose(bool disposing)
    27         {
    28             if (disposing)
    29             {
    30                 try
    31                 {
    32                     if (State != CommunicationState.Faulted)
    33                     {
    34                         Close();
    35                     }
    36                 }
    37                 finally
    38                 {
    39                     if (State != CommunicationState.Closed)
    40                     {
    41                         Abort();
    42                     }
    43                 }
    44             }
    45         }
    46 
    47         /// <summary>
    48         ///     Finalizer.
    49         /// </summary>
    50         ~*****Client()
    51         {
    52             Dispose(false);
    53         }
    54 
    55         #endregion
    56     }
    57 }
    View Code

    调用的地方可以直接使用using包起来了
    using(****Client client=new ****Client()){//处理逻辑,可以使用try包起来}

    3.我自己用到的处理方式,实现一个服务调用单例类,每个服务实现一个调用方法

     1    /// <summary>
     2         /// 调用SysSvc服务,统一处理TimeoutException和CommunicationException异常
     3         /// 用法:
     4         ///  List<ModuleEO/> list = SvcClient.Instance.SysClientCall(q => q.GetAllModules());
     5         /// </summary>
     6         /// <typeparam name="TResult">返回值</typeparam>
     7         /// <param name="func">调用的方法</param>
     8         /// <returns>泛型返回值</returns>
     9         public TResult SysClientCall<TResult>(Func<SysClient, TResult> func)
    10         {
    11             var client = this.GetSysClient();
    12             try
    13             {
    14                 TResult rec = func.Invoke(client);
    15                 client.Close();
    16                 return rec;
    17             }
    18             catch (TimeoutException ex)
    19             {
    20                 //服务器超时错误,提示用户即可。
    21                 client.Abort();
    22                 MessageBox.Show("服务器通讯超时,请重新尝试。");
    23             }
    24             catch (CommunicationException ex)
    25             {
    26                 //服务器连接通讯异常,提示用户即可。
    27                 client.Abort();
    28                 MessageBox.Show("服务器通讯错误,请重新尝试。");
    29             }
    30             catch (Exception ex)
    31             {
    32                 //未处理异常,重新抛出
    33                 client.Abort();
    34                 throw;
    35             }
    36             return default(TResult);
    37         }
    View Code

    参考链接:

    http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue

    http://stackoverflow.com/questions/6130331/how-to-handle-wcf-exceptions-consolidated-list-with-code

  • 相关阅读:
    计算机网络的三种通讯模式(单播,广播,组播)
    java字符串面试题
    java使用纯命令行打包项目
    java字节码的工具(含IDEA插件)
    Spring配置之context:annotation与、component-scan以及annotation-driven
    Java ThreadLocal的使用案例
    对称平方数(to_string函数,stoi函数真香)
    字符串最后一位长度
    缺失的括号
    数三角形
  • 原文地址:https://www.cnblogs.com/zhaobl/p/3179606.html
Copyright © 2011-2022 走看看