Przeglądaj źródła

[System] Change WebRequest::BeginGetRequestStream driven IAsyncResult::CompletedSynchronously to match .net. Fixes #32374

Marek Safar 9 lat temu
rodzic
commit
400b5eb8b4

+ 2 - 2
mcs/class/System/System.Net/HttpWebRequest.cs

@@ -963,7 +963,7 @@ namespace System.Net
 			initialMethod = method;
 
 			SimpleAsyncResult.RunWithLock (locker, CheckIfForceWrite, inner => {
-				var synch = inner.CompletedSynchronously;
+				var synch = inner.CompletedSynchronouslyPeek;
 
 				if (inner.GotException) {
 					aread.SetCompleted (synch, inner.Exception);
@@ -1374,7 +1374,7 @@ namespace System.Net
 					}
 
 					if (asyncWrite != null) {
-						asyncWrite.SetCompleted (inner.CompletedSynchronously, writeStream);
+						asyncWrite.SetCompleted (inner.CompletedSynchronouslyPeek, writeStream);
 						asyncWrite.DoCallback ();
 						asyncWrite = null;
 					}

+ 25 - 3
mcs/class/System/System.Net/SimpleAsyncResult.cs

@@ -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 {

+ 3 - 3
mcs/class/System/System.Net/WebConnectionStream.cs

@@ -719,12 +719,12 @@ namespace System.Net
 
 			SetHeadersAsync (true, inner => {
 				if (inner.GotException) {
-					result.SetCompleted (inner.CompletedSynchronously, inner.Exception);
+					result.SetCompleted (inner.CompletedSynchronouslyPeek, inner.Exception);
 					return;
 				}
 
 				if (cnc.Data.StatusCode != 0 && cnc.Data.StatusCode != 100) {
-					result.SetCompleted (inner.CompletedSynchronously);
+					result.SetCompleted (inner.CompletedSynchronouslyPeek);
 					return;
 				}
 
@@ -735,7 +735,7 @@ namespace System.Net
 
 				if (length == 0) {
 					complete_request_written = true;
-					result.SetCompleted (inner.CompletedSynchronously);
+					result.SetCompleted (inner.CompletedSynchronouslyPeek);
 					return;
 				}