Task2

这篇文章是第一篇Task文章的继续,比较啰嗦,本人也是靠msdn文档来学习的;

一、罗列一些属性

1、TaskCanceledException 类  ,表示一个用于告知任务取消的异常。https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.taskcanceledexception(v=vs.110).aspx

2、TaskContinuationOptions  Flag枚举,创建的任务指定行为,https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.taskcontinuationoptions(v=vs.110).aspx

3、TaskCreationOptions Flag枚举,指定用于控制任务的创建和执行的可选行为的标志。https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.taskcreationoptions(v=vs.110).aspx

4、TaskStatus 枚举,表示 Task的生命周期中的当前阶段。https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.taskstatus(v=vs.110).aspx

二、UnWrap  创建一个代理 Task 表示异步操作的 TryExecuteTaskInline。展开,解包,如返回值是Task<Task<int>>==>Task<int>

 1 // Invoking individual tasks is straightforward
 2             Task<int> t1 = RemoteIncrement(0);
 3             Console.WriteLine("Started RemoteIncrement(0)");
 4 
 5             // Chain together the results of (simulated) remote operations.
 6             // The use of Unwrap() instead of .Result below prevents this thread from blocking while setting up this continuation chain.
 7             Task<int> t2 = RemoteIncrement(4)
 8                 // RemoteIncrement() returns Task<int> so no unwrapping is needed for the first continuation.
 9                 .ContinueWith(t => RemoteIncrement(t.Result))
10                 // ContinueWith() returns Task<Task<int>>. Therefore unwrapping is needed.
11                 .Unwrap().ContinueWith(t => RemoteIncrement(t.Result))    
12                 .Unwrap().ContinueWith(t => RemoteIncrement(t.Result))    // and on it goes...
13                 .Unwrap();
14             Console.WriteLine("Started RemoteIncrement(...(RemoteIncrement(RemoteIncrement(4))...)");
15 
16             try
17             {
18                 t1.Wait();
19                 Console.WriteLine("Finished RemoteIncrement(0)
");
20 
21                 t2.Wait();
22                 Console.WriteLine("Finished RemoteIncrement(...(RemoteIncrement(RemoteIncrement(4))...)");
23             }
24             catch (AggregateException e)
25             {
26                 Console.WriteLine("A task has thrown the following (unexpected) exception:
{0}", e);
27             }
28 
29             Console.ReadKey();
30 //结果:
31 //Started RemoteIncrement(0)
32 //Started RemoteIncrement(...(RemoteIncrement(RemoteIncrement(4))...)
33 //Thread=10, Next=1
34 //Finished RemoteIncrement(0)
35 
36 //Thread=11, Next=5
37 //Thread=12, Next=6
38 //Thread=11, Next=7
39 //Thread=10, Next=8
40 //Finished RemoteIncrement(...(RemoteIncrement(RemoteIncrement(4))...)
View Code

三、TaskCompletionSource  

TaskCompletionSource 表示未绑定到委托的 Task<TResult> 的制造者方,并通过 Task 属性提供对使用者方的访问值并且通过TrySetResult方法可以设置Task的返回值。         task.IsFaulted 只有在ContinueWith里面才会等待任务执行完

 1  static public class Connector
 2     {
 3         /// <summary>
 4         /// begin connect
 5         /// </summary>
 6         /// <param name="endPoint"></param>
 7         /// <exception cref="ArgumentNullException">endPoint is null</exception>
 8         static public Task<Socket> Connect(EndPoint endPoint)
 9         {
10             if (endPoint == null) throw new ArgumentNullException("endPoint");
11 
12             var source = new TaskCompletionSource<Socket>();
13             var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
14 
15             var e = new SocketAsyncEventArgs();
16             e.UserToken = new Tuple<TaskCompletionSource<Socket>, Socket>(source, socket);
17             e.RemoteEndPoint = endPoint;
18             e.Completed += OnCompleted;
19 
20             bool completed = true;
21             try { completed = socket.ConnectAsync(e); }
22             catch (Exception ex) { source.TrySetException(ex); }
23             if (!completed) ThreadPool.QueueUserWorkItem(_ => OnCompleted(null, e));
24 
25             return source.Task;
26         }
27         /// <summary>
28         /// connect completed
29         /// </summary>
30         /// <param name="sender"></param>
31         /// <param name="e"></param>
32         static private void OnCompleted(object sender, SocketAsyncEventArgs e)
33         {
34             var t = e.UserToken as Tuple<TaskCompletionSource<Socket>, Socket>;
35             var source = t.Item1;
36             var socket = t.Item2;
37             var error = e.SocketError;
38 
39             e.UserToken = null;
40             e.Completed -= OnCompleted;
41             e.Dispose();
42 
43             if (error != SocketError.Success)
44             {
45                 socket.Close();
46                 source.TrySetException(new SocketException((int)error));
47                 return;
48             }
49 
50             source.TrySetResult(socket);
51         }
52     }
View Code
 1   TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
 2             Task<int> t1 = tcs1.Task;
 3             // Start a background task that will complete tcs1.Task
 4             Task.Factory.StartNew(() =>
 5             {
 6                 Thread.Sleep(2000);
 7                 tcs1.TrySetResult(15);
 8             });
 9             // The attempt to get the result of t1 blocks the current thread until the completion source gets signaled.
10             // It should be a wait of ~2000 ms.
11             Stopwatch sw = Stopwatch.StartNew();
12             int result = t1.Result;//获取结果的时候必须等待操作完成
13             sw.Stop();
14             Console.WriteLine("(ElapsedTime={0}): t1.Result={1} (expected 15) ", sw.ElapsedMilliseconds, result);
15 
16             // Alternatively, an exception can be manually set on a TaskCompletionSource.Task
17             TaskCompletionSource<int> tcs2 = new TaskCompletionSource<int>();
18             Task<int> t2 = tcs2.Task;
19 
20             // Start a background Task that will complete tcs2.Task with an exception
21             Task.Factory.StartNew(() =>
22             {
23                 Thread.Sleep(1000);
24 
25                 //tcs2.SetException(new InvalidOperationException("SIMULATED EXCEPTION"));
26                 //出现了异常,已被系统处理,但是下面获取Result属性的时候肯定出错
27                 tcs2.TrySetException(new InvalidOperationException("SIMULATED EXCEPTION"));
28             });
29 
30             // The attempt to get the result of t2 blocks the current thread until the completion source gets signaled with either a result or an exception.
31             // In either case it should be a wait of ~1000 ms.
32             //sw = Stopwatch.StartNew();
33             //解决异常1  调用 Task 的 Wait或者 Task.Result 方法时使用 try-catch 捕获异常:
34             //try
35             //{
36             //    result = t2.Result;//因为TrySetException,获取结果会抛错
37 
38             //    Console.WriteLine("t2.Result succeeded. THIS WAS NOT EXPECTED.");
39             //}
40             //catch (AggregateException e)
41             //{
42             //    Console.Write("(ElapsedTime={0}): ", sw.ElapsedMilliseconds);
43             //    Console.WriteLine("The following exceptions have been thrown by t2.Result: (THIS WAS EXPECTED)");
44             //    for (int j = 0; j < e.InnerExceptions.Count; j++)
45             //    {
46             //        Console.WriteLine("
-------------------------------------------------
{0}", e.InnerExceptions[j].ToString());
47             //    }
48             //}
49 
50             //解决异常2 在 Task 的 ContinueWith 方法中读取 Task 的 IsFaulted 属性是否出错:
51             t2.ContinueWith(task =>
52             {
53                 //task是上一个任务的结果, task.IsFaulted是判断有没有错误;如果不在ContinueWith里面或者在外面不用T2.Wait执行完,结果可能不
54                 //正确,因为IsFaulted属性不会阻塞线程的, 直接判断任务代码还没出现错误都是false,没有出错
55                 if (task.IsFaulted)
56                 {
57                     Console.WriteLine(task.Exception.GetBaseException());
58                     Console.WriteLine("出现了异常,已被系统处理,但是获取Result属性的时候肯定出错");
59                     Console.WriteLine(task.Result);
60                 }
61                 else
62                 {
63                     //没有异常才获取结果,要不然会抛错
64                     Console.WriteLine(task.Result);
65                 }
66             });
67             Console.ReadKey();
View Code

四、TaskFactory

在大多数情况下,我们无需实例化一个新 TaskFactory 实例。 相反,可以使用 Task.Factory 属性,它返回一个工厂对象,将使用默认值。 然后可以调用其方法来启动新任务或定义任务延续。

//想等待多个任务就用Task数组,使用Task.Await或者Task.Factory.ContinueWhenAll()

//创建一个任务,在数组中的任务之一通过调用完成后开始 ContinueWhenAny 方法。
//创建一个任务,在数组中的所有任务已都完成通过调用开始 ContinueWhenAll 方法。

 1 //TaskFactory 类
 2 Task[] tasks = new Task[2];
 3             String[] files = null;
 4             String[] dirs = null;
 5             String docsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
 6             tasks[0] = Task.Factory.StartNew(() => { Thread.Sleep(3000); files = Directory.GetFiles(docsDirectory); });
 7             tasks[1] = Task.Factory.StartNew(() => dirs = Directory.GetDirectories(docsDirectory));
 8             Console.WriteLine(files.Length);//不会等待的,报空异常
 9             Task.Factory.ContinueWhenAll(tasks, completedTasks =>
10             {
11                 Console.WriteLine("{0} contains: ", docsDirectory);
12                 Console.WriteLine("   {0} subdirectories", dirs.Length);
13                 Console.WriteLine("   {0} files", files.Length);
14             });
15             Console.ReadKey();
TaskFactory
            Task<string[]>[] tasks = new Task<string[]>[2];
            string docsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            tasks[0] = Task<string[]>.Factory.StartNew(() => Directory.GetFiles(docsDirectory));
            tasks[1] = Task<string[]>.Factory.StartNew(() => Directory.GetDirectories(docsDirectory));
            Task.Factory.ContinueWhenAll(tasks, completedTasks =>
            {
                Console.WriteLine("{0} contains: ", docsDirectory);
                Console.WriteLine("   {0} subdirectories", tasks[1].Result.Length);
                Console.WriteLine("   {0} files", tasks[0].Result.Length);
            });
            Console.ReadKey();

  

原文地址:https://www.cnblogs.com/entclark/p/8047323.html