-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAsyncResultVoid.cs
More file actions
144 lines (115 loc) · 4.32 KB
/
Copy pathAsyncResultVoid.cs
File metadata and controls
144 lines (115 loc) · 4.32 KB
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
143
144
using System;
using System.Threading;
namespace TicketProvider.Net
{
public class AsyncResultVoid : IAsyncResult
{
#region Variables
private readonly AsyncCallback _asyncCallback;
private readonly object _asyncState;
private enum AsyncResultCompleteState : int
{
Pending,
CompletedSynchronously,
CompletedAsynchronously
}
private Int32 _completeState;
private ManualResetEvent _asyncWaitHandle;
private Exception _ex;
#endregion
#region Properties
public object AsyncState
{
get { return _asyncState; }
}
public WaitHandle AsyncWaitHandle
{
get
{
if (_asyncWaitHandle == null)
{
bool isCompleted;
ManualResetEvent resetEvent;
// Create a new wait handle with the correct state.
isCompleted = IsCompleted;
resetEvent = new ManualResetEvent(isCompleted);
if (Interlocked.CompareExchange(ref _asyncWaitHandle,
resetEvent, null) != null)
{
// Another thread created this async results's wait event. Dispose the
// just created event.
resetEvent.Close();
resetEvent = null;
}
else
{
// Check if the operation was completed while creating the
// wait event.
if (!isCompleted && IsCompleted)
_asyncWaitHandle.Set();
}
}
return _asyncWaitHandle;
}
}
public bool CompletedSynchronously
{
get { return (Thread.VolatileRead(ref _completeState) == (Int32)AsyncResultCompleteState.CompletedSynchronously); }
}
public bool IsCompleted
{
get { return (Thread.VolatileRead(ref _completeState) != (Int32)AsyncResultCompleteState.Pending); }
}
#endregion
#region Functions
/// <summary>
/// Initializes a new instance of the AsyncResultNoResult class using the specified parameters.
/// </summary>
/// <param name="asyncCallback">Optional, may be null.</param>
/// <param name="state">Optional, may be null.</param>
public AsyncResultVoid(AsyncCallback asyncCallback, object state)
{
_asyncCallback = asyncCallback;
_asyncState = state;
}
/// <summary>
/// Sets the operation as completed, optionally setting an asynchronously thrown exception.
/// Passin null to indicate no exception was thrown.
/// </summary>
/// <param name="ex"></param>
/// <param name="completedSynchronously"></param>
public void Complete(Exception ex, bool completedSynchronously)
{
int state;
// Store the asynchronously thrown exception and verify the operation is not
// completed more than once.
_ex = ex;
state = Interlocked.Exchange(ref _completeState,
completedSynchronously ? (Int32)AsyncResultCompleteState.CompletedSynchronously : (Int32)AsyncResultCompleteState.CompletedAsynchronously);
if (state != (Int32)AsyncResultCompleteState.Pending)
throw new InvalidOperationException("The operation cannot be completed more than once");
// Set the wait event
if (_asyncWaitHandle != null)
_asyncWaitHandle.Set();
// Invoke callback
if (_asyncCallback != null)
_asyncCallback(this);
}
/// <summary>
/// Waits for completion of the operation.
/// </summary>
public void EndInvoke()
{
if (!IsCompleted)
{
AsyncWaitHandle.WaitOne();
AsyncWaitHandle.Close();
_asyncWaitHandle = null; // Allow early GC
}
// Throw asynchronously thrown exception.
if (_ex != null)
throw _ex;
}
#endregion
}
}