diff options
Diffstat (limited to 'ThirdParty/SmartThreadPool/CallerThreadContext.cs')
-rw-r--r-- | ThirdParty/SmartThreadPool/CallerThreadContext.cs | 309 |
1 files changed, 112 insertions, 197 deletions
diff --git a/ThirdParty/SmartThreadPool/CallerThreadContext.cs b/ThirdParty/SmartThreadPool/CallerThreadContext.cs index 6ea53f6..e63add5 100644 --- a/ThirdParty/SmartThreadPool/CallerThreadContext.cs +++ b/ThirdParty/SmartThreadPool/CallerThreadContext.cs | |||
@@ -1,3 +1,6 @@ | |||
1 | |||
2 | #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) | ||
3 | |||
1 | using System; | 4 | using System; |
2 | using System.Diagnostics; | 5 | using System.Diagnostics; |
3 | using System.Threading; | 6 | using System.Threading; |
@@ -6,218 +9,130 @@ using System.Web; | |||
6 | using System.Runtime.Remoting.Messaging; | 9 | using System.Runtime.Remoting.Messaging; |
7 | 10 | ||
8 | 11 | ||
9 | namespace Amib.Threading | 12 | namespace Amib.Threading.Internal |
10 | { | 13 | { |
11 | #region CallerThreadContext class | 14 | #region CallerThreadContext class |
12 | |||
13 | /// <summary> | ||
14 | /// This class stores the caller call context in order to restore | ||
15 | /// it when the work item is executed in the thread pool environment. | ||
16 | /// </summary> | ||
17 | internal class CallerThreadContext | ||
18 | { | ||
19 | #region Prepare reflection information | ||
20 | |||
21 | // Cached type information. | ||
22 | private static MethodInfo getLogicalCallContextMethodInfo = | ||
23 | typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); | ||
24 | |||
25 | private static MethodInfo setLogicalCallContextMethodInfo = | ||
26 | typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); | ||
27 | 15 | ||
28 | private static string HttpContextSlotName = GetHttpContextSlotName(); | 16 | /// <summary> |
17 | /// This class stores the caller call context in order to restore | ||
18 | /// it when the work item is executed in the thread pool environment. | ||
19 | /// </summary> | ||
20 | internal class CallerThreadContext | ||
21 | { | ||
22 | #region Prepare reflection information | ||
29 | 23 | ||
30 | private static string GetHttpContextSlotName() | 24 | // Cached type information. |
31 | { | 25 | private static readonly MethodInfo getLogicalCallContextMethodInfo = |
32 | FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); | 26 | typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); |
33 | 27 | ||
34 | if( fi != null ) | 28 | private static readonly MethodInfo setLogicalCallContextMethodInfo = |
35 | return (string)fi.GetValue(null); | 29 | typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); |
36 | else // Use the default "HttpContext" slot name | ||
37 | return "HttpContext"; | ||
38 | } | ||
39 | 30 | ||
40 | #endregion | 31 | private static string HttpContextSlotName = GetHttpContextSlotName(); |
41 | |||
42 | #region Private fields | ||
43 | |||
44 | private HttpContext _httpContext = null; | ||
45 | private LogicalCallContext _callContext = null; | ||
46 | |||
47 | #endregion | ||
48 | 32 | ||
49 | /// <summary> | 33 | private static string GetHttpContextSlotName() |
50 | /// Constructor | 34 | { |
51 | /// </summary> | 35 | FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); |
52 | private CallerThreadContext() | ||
53 | { | ||
54 | } | ||
55 | 36 | ||
56 | public bool CapturedCallContext | 37 | if (fi != null) |
57 | { | ||
58 | get | ||
59 | { | 38 | { |
60 | return (null != _callContext); | 39 | return (string) fi.GetValue(null); |
61 | } | 40 | } |
62 | } | ||
63 | 41 | ||
64 | public bool CapturedHttpContext | 42 | return "HttpContext"; |
65 | { | 43 | } |
66 | get | ||
67 | { | ||
68 | return (null != _httpContext); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /// <summary> | ||
73 | /// Captures the current thread context | ||
74 | /// </summary> | ||
75 | /// <returns></returns> | ||
76 | public static CallerThreadContext Capture( | ||
77 | bool captureCallContext, | ||
78 | bool captureHttpContext) | ||
79 | { | ||
80 | Debug.Assert(captureCallContext || captureHttpContext); | ||
81 | |||
82 | CallerThreadContext callerThreadContext = new CallerThreadContext(); | ||
83 | |||
84 | // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() | ||
85 | // Capture Call Context | ||
86 | if(captureCallContext && (getLogicalCallContextMethodInfo != null)) | ||
87 | { | ||
88 | callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); | ||
89 | if (callerThreadContext._callContext != null) | ||
90 | { | ||
91 | callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | // Capture httpContext | ||
96 | if (captureHttpContext && (null != HttpContext.Current)) | ||
97 | { | ||
98 | callerThreadContext._httpContext = HttpContext.Current; | ||
99 | } | ||
100 | |||
101 | return callerThreadContext; | ||
102 | } | ||
103 | 44 | ||
104 | /// <summary> | 45 | #endregion |
105 | /// Applies the thread context stored earlier | ||
106 | /// </summary> | ||
107 | /// <param name="callerThreadContext"></param> | ||
108 | public static void Apply(CallerThreadContext callerThreadContext) | ||
109 | { | ||
110 | if (null == callerThreadContext) | ||
111 | { | ||
112 | throw new ArgumentNullException("callerThreadContext"); | ||
113 | } | ||
114 | |||
115 | // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() | ||
116 | // Restore call context | ||
117 | if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) | ||
118 | { | ||
119 | setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); | ||
120 | } | ||
121 | |||
122 | // Restore HttpContext | ||
123 | if (callerThreadContext._httpContext != null) | ||
124 | { | ||
125 | CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | #endregion | ||
131 | |||
132 | } | ||
133 | 46 | ||
47 | #region Private fields | ||
134 | 48 | ||
135 | /* | 49 | private HttpContext _httpContext; |
136 | // Ami Bar | 50 | private LogicalCallContext _callContext; |
137 | // amibar@gmail.com | ||
138 | 51 | ||
139 | using System; | 52 | #endregion |
140 | using System.Threading; | ||
141 | using System.Globalization; | ||
142 | using System.Security.Principal; | ||
143 | using System.Reflection; | ||
144 | using System.Runtime.Remoting.Contexts; | ||
145 | 53 | ||
146 | namespace Amib.Threading.Internal | 54 | /// <summary> |
147 | { | 55 | /// Constructor |
148 | #region CallerThreadContext class | 56 | /// </summary> |
149 | 57 | private CallerThreadContext() | |
150 | /// <summary> | 58 | { |
151 | /// This class stores the caller thread context in order to restore | 59 | } |
152 | /// it when the work item is executed in the context of the thread | 60 | |
153 | /// from the pool. | 61 | public bool CapturedCallContext |
154 | /// Note that we can't store the thread's CompressedStack, because | 62 | { |
155 | /// it throws a security exception | 63 | get |
156 | /// </summary> | 64 | { |
157 | public class CallerThreadContext | 65 | return (null != _callContext); |
158 | { | 66 | } |
159 | private CultureInfo _culture = null; | 67 | } |
160 | private CultureInfo _cultureUI = null; | 68 | |
161 | private IPrincipal _principal; | 69 | public bool CapturedHttpContext |
162 | private System.Runtime.Remoting.Contexts.Context _context; | 70 | { |
163 | 71 | get | |
164 | private static FieldInfo _fieldInfo = GetFieldInfo(); | 72 | { |
165 | 73 | return (null != _httpContext); | |
166 | private static FieldInfo GetFieldInfo() | 74 | } |
167 | { | 75 | } |
168 | Type threadType = typeof(Thread); | 76 | |
169 | return threadType.GetField( | 77 | /// <summary> |
170 | "m_Context", | 78 | /// Captures the current thread context |
171 | BindingFlags.Instance | BindingFlags.NonPublic); | 79 | /// </summary> |
172 | } | 80 | /// <returns></returns> |
173 | 81 | public static CallerThreadContext Capture( | |
174 | /// <summary> | 82 | bool captureCallContext, |
175 | /// Constructor | 83 | bool captureHttpContext) |
176 | /// </summary> | 84 | { |
177 | private CallerThreadContext() | 85 | Debug.Assert(captureCallContext || captureHttpContext); |
178 | { | 86 | |
179 | } | 87 | CallerThreadContext callerThreadContext = new CallerThreadContext(); |
180 | 88 | ||
181 | /// <summary> | 89 | // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() |
182 | /// Captures the current thread context | 90 | // Capture Call Context |
183 | /// </summary> | 91 | if(captureCallContext && (getLogicalCallContextMethodInfo != null)) |
184 | /// <returns></returns> | 92 | { |
185 | public static CallerThreadContext Capture() | 93 | callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); |
186 | { | 94 | if (callerThreadContext._callContext != null) |
187 | CallerThreadContext callerThreadContext = new CallerThreadContext(); | 95 | { |
188 | 96 | callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); | |
189 | Thread thread = Thread.CurrentThread; | 97 | } |
190 | callerThreadContext._culture = thread.CurrentCulture; | 98 | } |
191 | callerThreadContext._cultureUI = thread.CurrentUICulture; | 99 | |
192 | callerThreadContext._principal = Thread.CurrentPrincipal; | 100 | // Capture httpContext |
193 | callerThreadContext._context = Thread.CurrentContext; | 101 | if (captureHttpContext && (null != HttpContext.Current)) |
194 | return callerThreadContext; | 102 | { |
195 | } | 103 | callerThreadContext._httpContext = HttpContext.Current; |
196 | 104 | } | |
197 | /// <summary> | 105 | |
198 | /// Applies the thread context stored earlier | 106 | return callerThreadContext; |
199 | /// </summary> | 107 | } |
200 | /// <param name="callerThreadContext"></param> | 108 | |
201 | public static void Apply(CallerThreadContext callerThreadContext) | 109 | /// <summary> |
202 | { | 110 | /// Applies the thread context stored earlier |
203 | Thread thread = Thread.CurrentThread; | 111 | /// </summary> |
204 | thread.CurrentCulture = callerThreadContext._culture; | 112 | /// <param name="callerThreadContext"></param> |
205 | thread.CurrentUICulture = callerThreadContext._cultureUI; | 113 | public static void Apply(CallerThreadContext callerThreadContext) |
206 | Thread.CurrentPrincipal = callerThreadContext._principal; | 114 | { |
207 | 115 | if (null == callerThreadContext) | |
208 | // Uncomment the following block to enable the Thread.CurrentThread | 116 | { |
209 | /* | 117 | throw new ArgumentNullException("callerThreadContext"); |
210 | if (null != _fieldInfo) | 118 | } |
211 | { | 119 | |
212 | _fieldInfo.SetValue( | 120 | // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() |
213 | Thread.CurrentThread, | 121 | // Restore call context |
214 | callerThreadContext._context); | 122 | if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) |
215 | } | 123 | { |
216 | * / | 124 | setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); |
217 | } | 125 | } |
218 | } | 126 | |
127 | // Restore HttpContext | ||
128 | if (callerThreadContext._httpContext != null) | ||
129 | { | ||
130 | HttpContext.Current = callerThreadContext._httpContext; | ||
131 | //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); | ||
132 | } | ||
133 | } | ||
134 | } | ||
219 | 135 | ||
220 | #endregion | 136 | #endregion |
221 | } | 137 | } |
222 | */ | 138 | #endif |
223 | |||