New test.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / Async / AsyncUtil.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc.Async {\r
14     using System;\r
15     using System.Threading;\r
16 \r
17     internal static class AsyncUtil {\r
18 \r
19         public static void WaitForAsyncResultCompletion(IAsyncResult asyncResult, HttpApplication app) {\r
20             // based on HttpServerUtility.ExecuteInternal()\r
21 \r
22             if (!asyncResult.IsCompleted) {\r
23                 // suspend app lock while waiting, else might deadlock\r
24                 bool needToRelock = false;\r
25 \r
26                 try {\r
27                     // .NET 2.0+ will not allow a ThreadAbortException to be thrown while a\r
28                     // thread is inside a finally block, so this pattern ensures that the\r
29                     // value of 'needToRelock' is correct.\r
30                     try { }\r
31                     finally {\r
32                         Monitor.Exit(app);\r
33                         needToRelock = true;\r
34                     }\r
35 \r
36                     WaitHandle waitHandle = asyncResult.AsyncWaitHandle;\r
37 \r
38                     if (waitHandle != null) {\r
39                         waitHandle.WaitOne();\r
40                     }\r
41                     else {\r
42                         while (!asyncResult.IsCompleted) {\r
43                             Thread.Sleep(1);\r
44                         }\r
45                     }\r
46                 }\r
47                 finally {\r
48                     if (needToRelock) {\r
49                         Monitor.Enter(app);\r
50                     }\r
51                 }\r
52             }\r
53         }\r
54 \r
55         public static AsyncCallback WrapCallbackForSynchronizedExecution(AsyncCallback callback, SynchronizationContext syncContext) {\r
56             if (callback == null || syncContext == null) {\r
57                 return callback;\r
58             }\r
59 \r
60             AsyncCallback newCallback = delegate(IAsyncResult asyncResult) {\r
61                 if (asyncResult.CompletedSynchronously) {\r
62                     callback(asyncResult);\r
63                 }\r
64                 else {\r
65                     // Only take the application lock if this request completed asynchronously,\r
66                     // else we might end up in a deadlock situation.\r
67                     syncContext.Sync(() => callback(asyncResult));\r
68                 }\r
69             };\r
70 \r
71             return newCallback;\r
72         }\r
73 \r
74     }\r
75 }\r