|
|
@@ -81,14 +81,14 @@ namespace System.Net
|
|
|
return running;
|
|
|
}, inner => {
|
|
|
if (inner.GotException) {
|
|
|
- if (inner.CompletedSynchronously)
|
|
|
+ if (inner.synch)
|
|
|
Monitor.Exit (locker);
|
|
|
callback (inner);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- if (!inner.CompletedSynchronously)
|
|
|
+ if (!inner.synch)
|
|
|
Monitor.Enter (locker);
|
|
|
|
|
|
callback (inner);
|
|
|
@@ -186,8 +186,30 @@ namespace System.Net
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ bool? user_read_synch;
|
|
|
+
|
|
|
public bool CompletedSynchronously {
|
|
|
- get { return synch; }
|
|
|
+ get {
|
|
|
+ //
|
|
|
+ // CompletedSynchronously (for System.Net networking stack) means "was the operation completed before the first time
|
|
|
+ // that somebody asked if it was completed synchronously"? They do this because some of their asynchronous operations
|
|
|
+ // (particularly those in the Socket class) will avoid the cost of capturing and transferring the ExecutionContext
|
|
|
+ // to the callback thread by checking CompletedSynchronously, and calling the callback from within BeginXxx instead of
|
|
|
+ // on the completion port thread if the native winsock call completes quickly.
|
|
|
+ //
|
|
|
+ // TODO: racy
|
|
|
+ if (user_read_synch != null)
|
|
|
+ return user_read_synch.Value;
|
|
|
+
|
|
|
+ user_read_synch = synch;
|
|
|
+ return user_read_synch.Value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ internal bool CompletedSynchronouslyPeek {
|
|
|
+ get {
|
|
|
+ return synch;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public bool IsCompleted {
|