-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCommunicationObjectHelper.cs
146 lines (130 loc) · 4.54 KB
/
CommunicationObjectHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
Copyright (c) 2011, thinktecture (http://www.thinktecture.com).
All rights reserved, comes as-is and without any warranty. Use of this
source file is governed by the license which is contained in LICENSE.TXT
in the distribution.
*/
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;
using Thinktecture.ServiceModel.Properties;
namespace Thinktecture.ServiceModel
{
/// <summary>
/// Contains the helper methods for managing the <see cref="CommunicationObject"/>'s life time.
/// </summary>
public static class CommunicationObjectHelper
{
/// <summary>
/// Invokes the specified delegate and cleans up the specified channel.
/// </summary>
public static void EnsureCleanup(object channel, Action action)
{
var commObj = channel as ICommunicationObject;
if (commObj == null)
{
throw new ArgumentException(Resources.NoCommunicationObject);
}
if (action == null)
{
throw new ArgumentException(Resources.NoValidDelegate);
}
try
{
action();
}
finally
{
TryCloseCommunicationObject(commObj);
}
}
/// <summary>
/// Invokes the specified delegate and retries the service operation call.
/// </summary>
/// <param name="action">The action.</param>
public static void RetryCall(Action action)
{
if (ConfigurationManager.AppSettings["retries"] == null)
throw new ConfigurationErrorsException(Resources.RetriesNotFound);
if (ConfigurationManager.AppSettings["timeToWait"] == null)
throw new ConfigurationErrorsException(Resources.TimeToWaitNotFound);
var retries = Convert.ToInt32(ConfigurationManager.AppSettings["retries"]);
var timeToWait = Convert.ToInt32(ConfigurationManager.AppSettings["timeToWait"]);
RetryCall(retries, timeToWait, action);
}
/// <summary>
/// Invokes the specified delegate and retries the service operation call.
/// </summary>
/// <param name="retries">The retries.</param>
/// <param name="action">The action.</param>
public static void RetryCall(int retries, Action action)
{
RetryCall(retries, 0, action);
}
/// <summary>
/// Invokes the specified delegate and retries the service operation call.
/// </summary>
/// <param name="retries">The retries.</param>
/// <param name="timeToWait">The time to wait.</param>
/// <param name="action">The action.</param>
public static void RetryCall(int retries, int timeToWait, Action action)
{
var currentRetry = 0;
var success = false;
var firstCall = true;
Exception exception = null;
while (!success && !(currentRetry == retries))
{
try
{
if (timeToWait > 0)
{
if (firstCall == false)
Thread.Sleep(timeToWait);
}
firstCall = false;
action();
success = true;
}
catch (TimeoutException tex)
{
currentRetry++;
exception = tex;
}
catch (CommunicationException cex)
{
currentRetry++;
exception = cex;
}
}
if (currentRetry == retries)
{
if (exception != null)
throw exception;
}
}
/// <summary>
/// Tries to gracefully close communication object.
/// </summary>
private static void TryCloseCommunicationObject(ICommunicationObject commObj)
{
if (commObj.State == CommunicationState.Faulted)
{
commObj.Abort();
}
else if (commObj.State != CommunicationState.Closed)
{
try
{
commObj.Close();
}
catch (CommunicationException)
{
commObj.Abort();
}
}
}
}
}