Browse Source

Rework TaskFactory.FromAsync, it was a bit messy.

Jérémie Laval 14 years ago
parent
commit
b4ddae3b51
1 changed files with 32 additions and 47 deletions
  1. 32 47
      mcs/class/corlib/System.Threading.Tasks/TaskFactory_T.cs

+ 32 - 47
mcs/class/corlib/System.Threading.Tasks/TaskFactory_T.cs

@@ -296,27 +296,24 @@ namespace System.Threading.Tasks
 			if ((creationOptions & FromAsyncOptionsNotSupported) != 0)
 				throw new ArgumentOutOfRangeException ("creationOptions");
 
-			var tcs = new TaskCompletionSource<TResult> (creationOptions);
-			tcs.Task.function = l => endMethod (asyncResult);
-
-			var task = tcs.Task;
+			var source = new CancellationTokenSource ();
+			var task = new Task<TResult> (l => {
+				try {
+					return endMethod (asyncResult);
+				} catch (OperationCanceledException) {
+					source.Cancel ();
+					source.Token.ThrowIfCancellationRequested ();
+				}
+				return default (TResult);
+			}, null, source.Token, creationOptions);
 
 			// Take quick path for completed operations
 			if (asyncResult.IsCompleted) {
-				try {
-					task.RunSynchronously (scheduler);
-				} catch (Exception e) {
-					tcs.TrySetException (e);
-				}
+				task.RunSynchronously (scheduler);
 			} else {
 				ThreadPool.RegisterWaitForSingleObject (asyncResult.AsyncWaitHandle,
-					delegate {
-						try {
-							task.RunSynchronously (scheduler);
-						} catch (Exception e) {
-							tcs.TrySetException (e);
-						}
-					}, null, Timeout.Infinite, true);
+				                                        (s, t) => task.RunSynchronously (scheduler),
+				                                        null, Timeout.Infinite, true);
 			}
 
 			return task;
@@ -335,7 +332,7 @@ namespace System.Threading.Tasks
 		}
 
 		internal static Task<TResult> FromAsyncBeginEnd (Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
-										  object state, TaskCreationOptions creationOptions)
+		                                                 object state, TaskCreationOptions creationOptions)
 		{
 			if (beginMethod == null)
 				throw new ArgumentNullException ("beginMethod");
@@ -347,13 +344,7 @@ namespace System.Threading.Tasks
 				throw new ArgumentOutOfRangeException ("creationOptions");
 
 			var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
-			beginMethod (l => {
-				try {
-					tcs.SetResult (endMethod (l));
-				} catch (Exception e) {
-					tcs.SetException (e);
-				}
-			}, state);
+			beginMethod (l => InnerInvoke (tcs, endMethod, l), state);
 
 			return tcs.Task;
 		}
@@ -370,8 +361,9 @@ namespace System.Threading.Tasks
 			return FromAsyncBeginEnd (beginMethod, endMethod, arg1, state, creationOptions);
 		}
 
-		internal static Task<TResult> FromAsyncBeginEnd<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
-										  TArg1 arg1, object state, TaskCreationOptions creationOptions)
+		internal static Task<TResult> FromAsyncBeginEnd<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+		                                                        Func<IAsyncResult, TResult> endMethod,
+		                                                        TArg1 arg1, object state, TaskCreationOptions creationOptions)
 		{
 			if (beginMethod == null)
 				throw new ArgumentNullException ("beginMethod");
@@ -383,13 +375,7 @@ namespace System.Threading.Tasks
 				throw new ArgumentOutOfRangeException ("creationOptions");
 
 			var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
-			beginMethod (arg1, l => {
-				try {
-					tcs.SetResult (endMethod (l));
-				} catch (Exception e) {
-					tcs.SetException (e);
-				}
-			}, state);
+			beginMethod (arg1, l => InnerInvoke (tcs, endMethod, l), state);
 
 			return tcs.Task;
 		}
@@ -419,13 +405,7 @@ namespace System.Threading.Tasks
 				throw new ArgumentOutOfRangeException ("creationOptions");
 
 			var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
-			beginMethod (arg1, arg2, l => {
-				try {
-					tcs.SetResult (endMethod (l));
-				} catch (Exception e) {
-					tcs.SetException (e);
-				}
-			}, state);
+			beginMethod (arg1, arg2, l => InnerInvoke (tcs, endMethod, l), state);
 
 			return tcs.Task;
 		}
@@ -456,13 +436,7 @@ namespace System.Threading.Tasks
 				throw new ArgumentOutOfRangeException ("creationOptions");
 
 			var tcs = new TaskCompletionSource<TResult> (state, creationOptions);
-			beginMethod (arg1, arg2, arg3, l => {
-				try {
-					tcs.SetResult (endMethod (l));
-				} catch (Exception e) {
-					tcs.SetException (e);
-				}
-			}, state);
+			beginMethod (arg1, arg2, arg3, l => InnerInvoke (tcs, endMethod, l), state);
 
 			return tcs.Task;
 		}
@@ -473,6 +447,17 @@ namespace System.Threading.Tasks
 		{
 			return scheduler ?? TaskScheduler.Current;
 		}
+
+		static void InnerInvoke (TaskCompletionSource<TResult> tcs, Func<IAsyncResult, TResult> endMethod, IAsyncResult l)
+		{
+			try {
+				tcs.SetResult (endMethod (l));
+			} catch (OperationCanceledException) {
+				tcs.SetCanceled ();
+			} catch (Exception e) {
+				tcs.SetException (e);
+			}
+		}
 	}
 }
 #endif