diff options
Diffstat (limited to '')
-rw-r--r-- | ThirdParty/SmartThreadPool/CallerThreadContext.cs | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/ThirdParty/SmartThreadPool/CallerThreadContext.cs b/ThirdParty/SmartThreadPool/CallerThreadContext.cs new file mode 100644 index 0000000..6ea53f6 --- /dev/null +++ b/ThirdParty/SmartThreadPool/CallerThreadContext.cs | |||
@@ -0,0 +1,223 @@ | |||
1 | using System; | ||
2 | using System.Diagnostics; | ||
3 | using System.Threading; | ||
4 | using System.Reflection; | ||
5 | using System.Web; | ||
6 | using System.Runtime.Remoting.Messaging; | ||
7 | |||
8 | |||
9 | namespace Amib.Threading | ||
10 | { | ||
11 | #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 | |||
28 | private static string HttpContextSlotName = GetHttpContextSlotName(); | ||
29 | |||
30 | private static string GetHttpContextSlotName() | ||
31 | { | ||
32 | FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); | ||
33 | |||
34 | if( fi != null ) | ||
35 | return (string)fi.GetValue(null); | ||
36 | else // Use the default "HttpContext" slot name | ||
37 | return "HttpContext"; | ||
38 | } | ||
39 | |||
40 | #endregion | ||
41 | |||
42 | #region Private fields | ||
43 | |||
44 | private HttpContext _httpContext = null; | ||
45 | private LogicalCallContext _callContext = null; | ||
46 | |||
47 | #endregion | ||
48 | |||
49 | /// <summary> | ||
50 | /// Constructor | ||
51 | /// </summary> | ||
52 | private CallerThreadContext() | ||
53 | { | ||
54 | } | ||
55 | |||
56 | public bool CapturedCallContext | ||
57 | { | ||
58 | get | ||
59 | { | ||
60 | return (null != _callContext); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | public bool CapturedHttpContext | ||
65 | { | ||
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 | |||
104 | /// <summary> | ||
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 | |||
134 | |||
135 | /* | ||
136 | // Ami Bar | ||
137 | // amibar@gmail.com | ||
138 | |||
139 | using System; | ||
140 | using System.Threading; | ||
141 | using System.Globalization; | ||
142 | using System.Security.Principal; | ||
143 | using System.Reflection; | ||
144 | using System.Runtime.Remoting.Contexts; | ||
145 | |||
146 | namespace Amib.Threading.Internal | ||
147 | { | ||
148 | #region CallerThreadContext class | ||
149 | |||
150 | /// <summary> | ||
151 | /// This class stores the caller thread context in order to restore | ||
152 | /// it when the work item is executed in the context of the thread | ||
153 | /// from the pool. | ||
154 | /// Note that we can't store the thread's CompressedStack, because | ||
155 | /// it throws a security exception | ||
156 | /// </summary> | ||
157 | public class CallerThreadContext | ||
158 | { | ||
159 | private CultureInfo _culture = null; | ||
160 | private CultureInfo _cultureUI = null; | ||
161 | private IPrincipal _principal; | ||
162 | private System.Runtime.Remoting.Contexts.Context _context; | ||
163 | |||
164 | private static FieldInfo _fieldInfo = GetFieldInfo(); | ||
165 | |||
166 | private static FieldInfo GetFieldInfo() | ||
167 | { | ||
168 | Type threadType = typeof(Thread); | ||
169 | return threadType.GetField( | ||
170 | "m_Context", | ||
171 | BindingFlags.Instance | BindingFlags.NonPublic); | ||
172 | } | ||
173 | |||
174 | /// <summary> | ||
175 | /// Constructor | ||
176 | /// </summary> | ||
177 | private CallerThreadContext() | ||
178 | { | ||
179 | } | ||
180 | |||
181 | /// <summary> | ||
182 | /// Captures the current thread context | ||
183 | /// </summary> | ||
184 | /// <returns></returns> | ||
185 | public static CallerThreadContext Capture() | ||
186 | { | ||
187 | CallerThreadContext callerThreadContext = new CallerThreadContext(); | ||
188 | |||
189 | Thread thread = Thread.CurrentThread; | ||
190 | callerThreadContext._culture = thread.CurrentCulture; | ||
191 | callerThreadContext._cultureUI = thread.CurrentUICulture; | ||
192 | callerThreadContext._principal = Thread.CurrentPrincipal; | ||
193 | callerThreadContext._context = Thread.CurrentContext; | ||
194 | return callerThreadContext; | ||
195 | } | ||
196 | |||
197 | /// <summary> | ||
198 | /// Applies the thread context stored earlier | ||
199 | /// </summary> | ||
200 | /// <param name="callerThreadContext"></param> | ||
201 | public static void Apply(CallerThreadContext callerThreadContext) | ||
202 | { | ||
203 | Thread thread = Thread.CurrentThread; | ||
204 | thread.CurrentCulture = callerThreadContext._culture; | ||
205 | thread.CurrentUICulture = callerThreadContext._cultureUI; | ||
206 | Thread.CurrentPrincipal = callerThreadContext._principal; | ||
207 | |||
208 | // Uncomment the following block to enable the Thread.CurrentThread | ||
209 | /* | ||
210 | if (null != _fieldInfo) | ||
211 | { | ||
212 | _fieldInfo.SetValue( | ||
213 | Thread.CurrentThread, | ||
214 | callerThreadContext._context); | ||
215 | } | ||
216 | * / | ||
217 | } | ||
218 | } | ||
219 | |||
220 | #endregion | ||
221 | } | ||
222 | */ | ||
223 | |||