zoukankan      html  css  js  c++  java
  • 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();
    

      

  • 相关阅读:
    49. 字母异位词分组
    73. 矩阵置零
    Razor语法问题(foreach里面嵌套if)
    多线程问题
    Get json formatted string from web by sending HttpWebRequest and then deserialize it to get needed data
    How to execute tons of tasks parallelly with TPL method?
    How to sort the dictionary by the value field
    How to customize the console applicaton
    What is the difference for delete/truncate/drop
    How to call C/C++ sytle function from C# solution?
  • 原文地址:https://www.cnblogs.com/entclark/p/8047323.html
Copyright © 2011-2022 走看看