在项目中采用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

 

 

 

 

posted on 2013-07-09 12:13  赵保龙  阅读(661)  评论(0编辑  收藏  举报