File: AsyncUtil.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (63 lines) | stat: -rw-r--r-- 2,217 bytes parent folder | download | duplicates (9)
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
namespace System.Web.Mvc.Async {
    using System;
    using System.Threading;

    internal static class AsyncUtil {

        public static void WaitForAsyncResultCompletion(IAsyncResult asyncResult, HttpApplication app) {
            // based on HttpServerUtility.ExecuteInternal()

            if (!asyncResult.IsCompleted) {
                // suspend app lock while waiting, else might deadlock
                bool needToRelock = false;

                try {
                    // .NET 2.0+ will not allow a ThreadAbortException to be thrown while a
                    // thread is inside a finally block, so this pattern ensures that the
                    // value of 'needToRelock' is correct.
                    try { }
                    finally {
                        Monitor.Exit(app);
                        needToRelock = true;
                    }

                    WaitHandle waitHandle = asyncResult.AsyncWaitHandle;

                    if (waitHandle != null) {
                        waitHandle.WaitOne();
                    }
                    else {
                        while (!asyncResult.IsCompleted) {
                            Thread.Sleep(1);
                        }
                    }
                }
                finally {
                    if (needToRelock) {
                        Monitor.Enter(app);
                    }
                }
            }
        }

        public static AsyncCallback WrapCallbackForSynchronizedExecution(AsyncCallback callback, SynchronizationContext syncContext) {
            if (callback == null || syncContext == null) {
                return callback;
            }

            AsyncCallback newCallback = delegate(IAsyncResult asyncResult) {
                if (asyncResult.CompletedSynchronously) {
                    callback(asyncResult);
                }
                else {
                    // Only take the application lock if this request completed asynchronously,
                    // else we might end up in a deadlock situation.
                    syncContext.Sync(() => callback(asyncResult));
                }
            };

            return newCallback;
        }

    }
}