-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathHttpAsyncResult.cs
142 lines (114 loc) · 5.26 KB
/
HttpAsyncResult.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
//------------------------------------------------------------------------------
// <copyright file="HttpAsyncResult.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* ASP.NET simple internal implementation of IAsyncResult
*
* Copyright (c) 2000 Microsoft Corporation
*/
namespace System.Web {
using System;
using System.Threading;
using System.Web.Util;
internal class HttpAsyncResult : IAsyncResult {
private AsyncCallback _callback;
private Object _asyncState;
private bool _completed;
private bool _completedSynchronously;
private Object _result;
private Exception _error;
private Thread _threadWhichStartedOperation;
// pipeline support
private RequestNotificationStatus
_status;
/*
* Constructor with pending result
*/
internal HttpAsyncResult(AsyncCallback cb, Object state) {
_callback = cb;
_asyncState = state;
_status = RequestNotificationStatus.Continue;
}
/*
* Constructor with known result
*/
internal HttpAsyncResult(AsyncCallback cb, Object state,
bool completed, Object result, Exception error) {
_callback = cb;
_asyncState = state;
_completed = completed;
_completedSynchronously = completed;
_result = result;
_error = error;
_status = RequestNotificationStatus.Continue;
if (_completed && _callback != null)
_callback(this);
}
internal void SetComplete() {
_completed = true;
}
/*
* Helper method to process completions
*/
internal void Complete(bool synchronous, Object result, Exception error, RequestNotificationStatus status) {
if (Volatile.Read(ref _threadWhichStartedOperation) == Thread.CurrentThread) {
// If we're calling Complete on the same thread which kicked off the operation, then
// we ignore the 'synchronous' value that the caller provided to us since we know
// for a fact that this is really a synchronous completion. This is only checked if
// the caller calls the MarkCallToBeginMethod* routines below.
synchronous = true;
}
_completed = true;
_completedSynchronously = synchronous;
_result = result;
_error = error;
_status = status;
if (_callback != null)
_callback(this);
}
internal void Complete(bool synchronous, Object result, Exception error) {
Complete(synchronous, result, error, RequestNotificationStatus.Continue);
}
/*
* Helper method to implement End call to async method
*/
internal Object End() {
if (_error != null)
throw new HttpException(null, _error);
return _result;
}
// If the caller needs to invoke an asynchronous method where the only way of knowing whether the
// method actually completed synchronously is to inspect which thread the callback was invoked on,
// then the caller should surround the asynchronous call with calls to the below Started / Completed
// methods. The callback can compare the captured thread against the current thread to see if the
// completion was synchronous. The caller calls the Completed method when unwinding so that the
// captured thread can be cleared out, preventing an asynchronous invocation on the same thread
// from being mistaken for a synchronous invocation.
internal void MarkCallToBeginMethodStarted() {
Thread originalThread = Interlocked.CompareExchange(ref _threadWhichStartedOperation, Thread.CurrentThread, null);
Debug.Assert(originalThread == null, "Another thread already called MarkCallToBeginMethodStarted.");
}
internal void MarkCallToBeginMethodCompleted() {
Thread originalThread = Interlocked.Exchange(ref _threadWhichStartedOperation, null);
Debug.Assert(originalThread == Thread.CurrentThread, "This thread did not call MarkCallToBeginMethodStarted.");
}
//
// Properties that are not part of IAsyncResult
//
internal Exception Error { get { return _error;}}
internal RequestNotificationStatus Status {
get {
return _status;
}
}
//
// IAsyncResult implementation
//
public bool IsCompleted { get { return _completed;}}
public bool CompletedSynchronously { get { return _completedSynchronously;}}
public Object AsyncState { get { return _asyncState;}}
public WaitHandle AsyncWaitHandle { get { return null;}} // wait not supported
}
}